簡體   English   中英

當兩個表中都不存在ID時,使用Linq連接實體框架表

[英]Joining Entity Framework tables using Linq when IDs do not exist in both tables

以下是我使用實體框架在數據庫中生成表的類。 我希望能夠將此表鏈接到另一個表Property 但是,我的代碼設置方式是在Instruction表中沒有Id列,在類中沒有Property屬性,然后在實際數據庫中生成了PropertyId列,但是由於Property屬性不是Id I我無法使用Linq聯接這些表。

指令表

[Table("Instruction")]
public class Instruction
    {
        [Key]
        public int Id { get; set; }
        public InstructionTypes InstructionType { get; set; }
        public Property Property { get; set; } //Generates the EF property FK, but is not an ID so therefore cannot be used in linq.
    }

屬性表

[Table("Property")]
    public partial class Property
    {
        [Key]
        public int Id { get; set; }
        public Address Correspondence { get; set; }
    }

聯接查詢

var instruction = 
                from instructions in _context.Instructions
                join properties in _context.Properties on instructions.Property equals properties.Id
                where ...

上面的查詢給出了一個編譯器錯誤:`join子句中的表達式之一的類型不正確。

當我嘗試使用屬性對象與propertyId聯接時,正在生成此錯誤。

如何更改此查詢,以便能夠聯接這兩個表?

您似乎是linq的新手。 因此,您仍在思考,好像您仍在sql世界中一樣。

對於linq to實體,使用join是一個例外。 EF使用導航屬性以靜默方式生成SQL join

因此,您的查詢可以是:

var instruction = 
            from instruction in _context.Instructions                
            where instruction.Porperty.Correspondence.Contains("abc");

然后您可以訪問

instruction.First().Property.Correspondence

作為一種好習慣,您可以將外鍵聲明為類成員,並使用流暢的API綁定它們。

要測試您可以使用以下代碼,

//assuming that Instructions is a DbSet<Instruction>
using (var context = new MyContext() ) {
    context.Instructions.Add(
        new instruction {
            Property = new Property {
                Correspondence = new Address {}
            }
        });
}

using (var context = new MyContext() ) {
    var c = context.Instructions.First();
    console.WriteLine($"{c.Id}, {c?.Property.Id}, {c?.Property?.Correspondence.Id}");
});

在所有情況的99%中,您都不希望使用join運算符。 使用導航屬性時,Entity Framework會自動為您生成SQL JOINS。

var instruction = await _context.Instructions.Where(i => i.Property...).FirstOrDefaultAsync().ConfigureAwait(false);

請注意,根據您使用的是EF6還是EF Core或不同的配置,可能會禁用“延遲加載”(如果沒有,則強烈建議您禁用它,因為這是一個巨大的性能瓶頸)。

因此,您必須使用Include方法來熱切加載相關實體。

var instruction = await _context.Instructions.Include(i => i.Property).Where(i => i.Property...).FirstOrDefaultAsync().ConfigureAwait(false);

但是在執行此操作之前,請先考慮一下是否確實需要該Instruction 如果沒有,您的代碼可能變成:

var property = await _context.Properties.Where(p => p.Instructions.Any(i => ...)).FirstOrDefaultAsync().ConfigureAwait(false);

請注意,您必須擴展Property類才能使其具有向后引用

public partial class Property
{
    // No need for the Key attribute, as this is convention
    public int Id { get; set; }
    public Address Correspondence { get; set; }
    public int CorrespondenceId { get; set; } // Not needed in this scenario, but good practice
    public ICollection<Instruction> Instructions { get; } = new HashSet<Instruction>();
}

暫無
暫無

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

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