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