gpt4 book ai didi

c# - DbSet、ModelBuilder 和 EF 导航属性

转载 作者:行者123 更新时间:2023-11-30 22:12:18 27 4
gpt4 key购买 nike

我正在尝试实现一个 Multi-Tenancy 应用程序,我通过租户对象查询数据库,而不是直接脱离上下文。在我有这个之前:

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() 和其他数据库的调用查询中断。

如果我使用 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);
}

关于c# - DbSet、ModelBuilder 和 EF 导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19758080/

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