gpt4 book ai didi

c# - 如何使用 Entity Framework 和 MVC4 在 Multi-Tenancy 应用程序中过滤 DbContext

转载 作者:太空狗 更新时间:2023-10-29 17:59:28 25 4
gpt4 key购买 nike

我正在使用 MVC4EF5 开发一个 Multi-Tenancy 网络应用程序。我之前问过这个关于过滤我的 DbContext 的问题:Is it bad practice to filter by ID within the repository pattern

显然,我的方法是合理的,但有人建议我不要在单个存储库中处理所有过滤,而是使用存储库或 DBContextWrapper 提供一个已经过滤到租户级别的上下文可以为您的 [my] 普通存储库提供数据的类”

不幸的是,我不是 MVC 专家,所以我开始尽可能地实现它,但是在研究 EF 中其他 Multi-Tenancy 应用程序的过滤时,我发现了一个关于非常相似的案例 Multi-tenancy web application with filtered dbContext 的问题,尽管完全无法理解它的答案。

在我的应用程序中,CompanyID 是 User 类的一个属性,因此应该直接从经过身份验证的用户那里获取。例如:

int CompanyID = db.Users.Single(u => u.Email == User.Identity.Name).CompanyID;

我目前的方法似乎确实有效,但我很确定我的做法是错误的和/或根据我在其他问题中看到的关于做同样事情的内容,我的做法效率低下。在另一个问题 Solutions for a simple multi tenant web application with entity framework 反射用于执行此操作,但我无法确定它是否适用于我的情况,甚至无法确定如何使用它。

如果有人能解释解决此问题的最佳方法,以及不同方法的优缺点,我将不胜感激。谢谢:)

我目前的实现如下:

数据库

  • 一个数据库,多个租户。
  • 所有表都以某种方式链接回公司表,但并非所有表都有 CompanyID 字段。

TestController.cs

public class TestController : Controller
{
private BookingSystemEntities db = new BookingSystemEntities();
public ActionResult Index()
{
var user = db.Users.Single(u => u.Email == User.Identity.Name);
IBookingSystemRepository rep = new BookingSystemRepository(db, user);
return View(rep.GetAppointments(false));
}

}

BookingSystemRepository.cs

public class BookingSystemRepository : IBookingSystemRepository
{
private CompanyBookingSystemRepository db;

public BookingSystemRepository(BookingSystemEntities context, User user)
{
this.db = new CompanyBookingSystemRepository(context, user);
}

public IEnumerable<Appointment> GetAppointments()
{ return GetAppointments(false); }

public IEnumerable<Appointment> GetAppointments(bool includeDeleted)
{
return includeDeleted
? db.Appointments
: db.Appointments.Where(a => a.Deleted.HasValue);
}

public IEnumerable<Client> GetClients()
{ return GetClients(false); }

public IEnumerable<Client> GetClients(bool includeDeleted)
{
return includeDeleted
? db.Clients
: db.Clients.Where(c => c.Deleted.HasValue);
}

public void Save()
{
db.SaveChanges();
}

public void Dispose()
{
if (db != null)
db.Dispose();
}
}

CompanyBookingSystemRepository.cs

public class CompanyBookingSystemRepository
{
private BookingSystemEntities db;
private User User;
public IEnumerable<Appointment> Appointments { get { return db.Appointments.Where(a => a.User.CompanyID == User.CompanyID).AsEnumerable<Appointment>(); } }
public IEnumerable<Client> Clients { get { return db.Clients.Where(a => a.CompanyID == User.CompanyID).AsEnumerable<Client>(); } }

public CompanyBookingSystemRepository(BookingSystemEntities context, User user)
{
db = context;
this.User = user;
}

public void SaveChanges()
{
db.SaveChanges();
}

public void Dispose()
{
if (db != null)
db.Dispose();
}
}

最佳答案

与您提供的其他示例相比,我更喜欢您的方法。基于登录用户的过滤应该是确保您正确过滤数据的最有效方法,假设每个租户运行相同的代码库和域。 (如果没有,您也可以利用它们进行过滤。)

如果您担心使用没有 CompanyID 的过滤表的数据库性能,您可以有目的地对数据库进行非规范化以在这些表中包含该字段。

您引用的反射方法虽然优雅,但似乎过于复杂并且比在您的数据库调用中包含 CompanyID 的开销要大得多(特别是因为数据库调用在两个实例中都发生)。

编辑(评论后):

至于其余部分,您似乎编写了很多不必要的多余代码(至少在上面引用的示例中没有)。我不一定理解你为什么要区分 BookingSystemRepository 和 CompanyBookingSystemRepository 因为从你的代码看来前者的存在只是为了将调用传递给后者,后者只是使用 UserID 过滤结果(是否有过这样的情况你不会过滤这些结果?)。

只需将方法更改为:

,您就可以完全消除这两个类(以及您在评论中引用的问题):

public class TestController : Controller
{
private BookingSystemEntities db = new BookingSystemEntities();
public ActionResult Index()
{
var user = db.Users.Single(u => u.Email == User.Identity.Name);
var appointments = db.Appointments.Where(a => a.User.CompanyID == user.CompanyID).AsEnumerable();
return View(appointments);
}

public override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}

从那里开始,如果您担心性能,您真的应该在数据库中进行所有过滤,然后只调用这些过程来返回您的数据。

关于c# - 如何使用 Entity Framework 和 MVC4 在 Multi-Tenancy 应用程序中过滤 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17190132/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com