以下是我使用实体框架在数据库中生成表的类。我希望能够将此表链接到另一个表Property
。但是,我的代码的设置方式是Instruction
表中没有Id列,类中有Property属性,然后在实际数据库中生成了PropertyId列,但是由于Property属性是不是Id,我无法使用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联接时,正在生成此错误。
如何更改此查询,以便能够联接这两个表?
答案 0 :(得分:0)
您似乎是linq的新手。因此,您仍在思考,好像您仍在sql世界中一样。
对于实体使用linq,使用join
是一个例外。 SQL join
由EF使用导航属性静默生成。
因此您的查询可以是:
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}");
});
答案 1 :(得分:0)
在所有情况的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>();
}