[英]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.