簡體   English   中英

實體框架和LINQ左連接並包含在同一表中

[英]Entity Framework and LINQ left join and include on same table

我的用戶具有以下類結構,以及它們所關聯的不同公司所具有的權限:

public class User
{
    public Guid Id { get; set; }
    public List<Permission> Permissions { get; set; }
    public Company DefaultCompany { get; set; }
}

public class Permission
{
    public User User { get; set; }
    public Company Company { get; set; }
    public int PermissionLevel { get; set; }
}

public class Company
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

這將產生三個SQL表。 Permission.User_Id> User.Id和Permission.Company_Id> Company.Id之間有一個FK。 User.DefaultCompany與Company表之間沒有明確的關系(即FK)。 這是有目的的,因為在我們的數據庫模式中有傳統的選擇。

我還有一個數據庫存儲庫方法,可以通過其ID來吸引用戶,並包括完整的公司記錄:

public User GetById(Guid Id)
{
    return (from r in this.Context.Users.Include("Permissions.Company")
        where r.Id == Id
        select r)
        .SingleOrDefault();
}

這可以正常工作,但是它沒有設置DefaultCompany屬性。 因此,我嘗試通過將此方法更改為以下內容來進行設置。 值得指出的是,代表DefaultCompany的Company記錄與User共享相同的ID值。

public User GetById(Guid Id)
{
    return (from r in this.Context.Users.Include("Permissions.Company")
            where r.Id == Id
            join c in this.Context.Companies on r.Id equals c.Id into companies
            from company in companies.DefaultIfEmpty()
            select new { User = r, Company = company })
            .ToList()
            .Select(p => { p.User.DefaultCompany = p.Company; return p.User; })
            .SingleOrDefault();
}

實際上,這確實設置了DefaultCompany但是它的副作用是沒有選擇“ Permissions列表。 我可以通過兩個單獨的操作來完成所有這些操作,如以下代碼所示,但是如果不需要的話,我不想兩次訪問數據庫。

public User GetById(Guid Id)
{
    var u = (from r in this.Context.Users.Include("Permissions.Company")
            where r.Id == Id
            select r)
            .SingleOrDefault();

    u.DefaultCompany = (from r in this.Context.Companies where r.Id == u.Id select r).SingleOrDefault();

    return u;
}

還有另一種方法可以做到這一點嗎?

編輯:解釋結果SQL數據模型和其他示例。

有兩種可能的解決方案。

最干凈的方法是使用Fluent API來指示該模型,即用戶與公司之間存在1對1的關系。

重寫上下文的OnModelCreating(DbModelBuilder modelBuilder)方法。

在其中配置如下的1 ro 1關系:

 modelBuilder.Entity<User>()
             .HasOptional(u => u.DefaultCompany)
             .WithRequired();

注意:使用此配置時,有1個用戶與0個或1個默認公司的關系(請注意HasOptional中的HasOptional )。 並且默認公司必須在另一邊有一個用戶。 配置了1到1(或1到0..1)關系后,EF將自動使用相關表的PK在它們之間創建關系。 您可以使用其他Fluent API函數微調關系

之后,您可以使用Include()包括DefaultCompany

User user = ctx.Users
               .Include(u => u.DefaultCompany)
               .SingleOrDefault(u => u.Id == userId);

另一個更丑陋的解決方案是使用第二個查詢,並將丟失的權限包括在投影中,以強制EF從數據庫中恢復它們。

// ...
select new { User = r, Company = company, Companies = r.Permissions } 
// ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM