[英]DbSet, ModelBuilder, and EF Navigation Properties
我正在尝试实现一个多租户应用程序,在这里我通过租户对象而不是直接从上下文查询数据库。 在此之前:
public User GetUserByEmail(string email)
{
using (var db = CreateContext())
{
return db.Users.FirstOrDefault(u => u.Email.Equals(email, StringComparison.OrdinalIgnoreCase));
}
}
现在我有这个:
public User GetUserByEmail(string email)
{
using (var db = CreateContext())
{
return _tenant.Users.FirstOrDefault(u => u.Email.Equals(email, StringComparison.OrdinalIgnoreCase));
}
}
其中“租户”为:
public class Tenant
{
public Tenant()
{
}
[Key]
[Required]
public int TenantId { get; set; }
public virtual DbSet<User> Users { get; set; }
// etc
}
我的用户模型具有以下内容:
public virtual List<Tenant> Tenants { get; set; }
在我的上下文配置中,我具有以下内容:
modelBuilder.Entity<Tenant>()
.HasMany(e => e.Users)
.WithMany()
.Map(m =>
{
m.ToTable("UserTenantJoin");
m.MapLeftKey("TenantId");
m.MapRightKey("UserId");
});
但是我遇到了一个问题,那就是DbSet与上面的ModelBuilder不兼容-它使HasMany感到不安,他说不能从用法中推断出DbSet的使用。
我改用了ICollection,但是在我的服务层中,对_tenant.Users.Include(stuff)
或Find()
所有调用都_tenant.Users.Include(stuff)
,其他数据库查询也中断了。
如果使用ICollection会中断服务方法的示例:
public User GetUserWithInterestsAndAptitudes(string username)
{
using (var db = CreateContext())
{
return _tenant.Users. // can't use .Include on ICollection
Include(u => u.Relationships).
Include(u => u.Interests).
Include(u => u.Interests.Select(s => s.Subject)).
Include(u => u.Interests.Select(s => s.Aptitude)).
FirstOrDefault(s => s.Username.Equals(username, StringComparison.OrdinalIgnoreCase));
}
}
我希望有一个解决方案,使我可以保持导航属性的可查询性,而无需重新构建服务层。
一种选择是,我通过db.Users
将所有内容恢复为使用上下文,然后向每个查询添加另一个条件.Where(u => u.TenantId == _tenant.TenantId)
-但我正尝试避免这种情况。
在这里的任何帮助将不胜感激。
我有一个类似于您要避免的解决方案。
我有一个真正的DbContext,只能通过TenantContext访问。
public class RealContext
{
public DbSet<User> Users { get; set; }
[...]
}
public class TenantContext
{
private RealContext realContext;
private int tenantId;
public TenantContext(int tenantId)
{
realContext = new RealContext();
this.tenantId= tenantId;
}
public IQueryable<User> Users { get { FilterTenant(realContext.Users); } }
private IQueryable<T> FilterTenant<T>(IQueryable<T> values) where T : class, ITenantData
{
return values.Where(x => x.TenantId == tenantId);
}
public int SaveChanges()
{
ApplyTenantIds();
return realContext.SaveChanges();
}
}
使用这种方法,我确定没有正确的租户就无法发送查询。 为了从上下文中添加和删除项目,我使用这两种通用方法。
public void Remove<T>(params T[] items) where T : class, ITenantData
{
var set = realContext.Set<T>();
foreach(var item in items)
set.Remove(item);
}
public void Add<T>(params T[] items) where T : class, ITenantData
{
var set = realContext.Set<T>();
foreach (var item in items)
set.Add(item);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.