Multitenancy with Entity Framework

Asked

Viewed 158 times

3

I have my application, which shares the same database with all my customers.

Separating them only by a column of the table Empresa_Id, all my actions, Save, List, Edit, Delete are done by my Pository.

In my Repospository I pass the Company Id, always before executing the action. But in my Edit, as it sends the ID through the URL to return to the View, I cannot handle it, and others may have access to other people’s data.

So what’s flawed is this method here from Repository:

public virtual T getById(int id)
{
  return _dbSet.Find(id);
}

Any idea to get around this problem?

I even thought about changing my PK all to GUID, but I’m afraid my queries will be too slow (since the Entity Framework is famous for being a slow ORM compared to others).

  • 1

    Tiago, so I read already...but it’s complicated you know, I’m going through something very "similar" to what you mentioned... I have even made this way, to return Null if it is not the same "Company" etc...

  • James, out of curiosity, succeeded by making that condition and returning Null in his Dit in the Pository ?

  • Sorry James, confused, your "Get" returning Null when it is not from Empresaid

  • 1

    Tiago, as I’m using Asp.net Identity, I leave Empresaid in Claims even... then I don’t need to search from the bank or something, it’s already in memory

1 answer

2


If you cannot uniquely identify any and all records of the entities in your application, something is very wrong.

In the Multilieutenant model, the key does not necessarily need to be composed. The mistake you are having is because the entity was built more or less like this:

public class Entidade
{
    [Key, Column(Order=1)]
    public int EmpresaId { get; set; }
    [Key, Column(Order=2)]
    public int EntidadeId { get; set; }
    ...
}

Sometimes I have warned about this type of approach. The right thing would be:

public class Entidade
{
    [Key]
    public int EntidadeId { get; set; }
    public int EmpresaId { get; set; }
    ...
}

So you can uniquely identify your records and put the access check rules in the layer Controller, or through Filters, as an example in this answer (the example is for log, but it is a basis for an authorization filter).

Now, if really it is necessary to use composite key in the application, you can change the request link to act as follows:

http://localhost/Entidades/Edit/1?EmpresaId=2

The method in Controller, so it would look like this:

public ActionResult Edit(int id, int EmpresaId) {
    ...
}
  • Gypsy, you say "through Filters" has some example for this?

  • So Gypsy, as I was even talking to Tiago, I do not pass by parameter and yes, picked up from the user logged through the Claims, I was curious about the filter, maybe not create the filter but the logic that you tried to pass when quoted

  • @Rod I put a link to you.

  • No, all my classes inherit from a modelBase where I have only [Index] public int Empresaid {get;set;}

  • I saw the error I was having, I use a Hidden in my Edit to leave the entity Id, and even sending a Viewmodel with Id=0 he is assigning the URL Id to this Hidden, that was what was giving me error

Browser other questions tagged

You are not signed in. Login or sign up in order to post.