有人能解释为什么这不起作用吗?
在数据库中,我们有一个带有IdEmployee列的Employees。我们还有一些带有外键的表。
说我们有这样的事情:
var employee = dataContext.Employees.First(<some predicate>);
var someEntity = dataContext.SomeEntities.First(<some predicate>);
为什么这不起作用:
var something = someEntity.SomeThings.First(t => t.Employee == employee);
虽然这样做:
var something = someEntity.SomeThings.First(t => t.IdEmployee == employee.IdEmployee);
我不明白......是不是第一个版本应该有效? Employee实体来自相同的datacontext ...
答案 0 :(得分:1)
编辑:前面的解释是错误的,因为'它适用于我的机器':
var contract = dataContext.Contracts.First();
var room = dataContext.Rooms.First(r => r.Contract == contract);
你的班级之间的联系必须打破一些东西。
您可以使用
获取已执行的命令 var command = dataContext.GetCommand(
dataContext.Rooms.Where(r => r.Contract == contract))
.CommandText;
生成的命令文本为:
SELECT ... FROM [Rooms] AS [t0]
WHERE [t0].[ContractId] = @p0
因此我们可以看到主键是从实体类型中找到的......
不是第一个版本 工作? Employee实体来自 相同的datacontext ...
是但是lambda表达式转换为SQL脚本,似乎linq Sql脚本构建器不会尝试查找实体键来生成请求。
linq to Sql命令构建器使用lambda内容作为表达式&lt;&gt;用于构建查询文本的树。要执行此操作,它期望lambda包含引用实体属性的表达式。
这里的问题似乎是它引用了实体,而不是属性。
以下查询
var something = someEntity.SomeThings
.First(t => t.IdEmployee == employee.IdEmployee);
生成类似
的SqlSELECT ... FROM SomThings
WHERE IdEmployee = @idEmployee
使用lambda中的属性名称找到表列。
在另一种情况下,没有属性名称......
答案 1 :(得分:1)
由于装载松弛。 someEntity.Employee属性未从DB加载。如果你想 加载它,你应该在从DB中检索数据之前使用“DataLoadOptions”,语法如下:
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<SomeThing>(s=>SomeProperty);
dataContext.LoadOptions = options;
答案 2 :(得分:0)
我认为第一个不起作用,因为类型不同,但在第二个它们不是(你在第二个中处理整数)。
您应该覆盖Equals(和GetHashCode)方法,以实现您自己的相等比较。
修改
正如你已经指出它们必须是同一类型,因为如果不是它会在编译时失败,但我会坚持认为实现你自己的Equals和GetHashCode函数可能会很方便。我认为你的问题就在那里。我现在可以回想一下这个链接,但是我已经在某个地方读到了.NET中的平等比较有点棘手。
检查此示例:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Employee a = new Employee(1);
Employee b = new Employee(1);
Console.WriteLine("a == b := {0}", a == b);
Console.ReadLine();
}
}
class Employee
{
private int id;
public Employee(int id) { this.id = id; }
}
}
输出结果为:
a == b := False
这是因为.NET内部使用Object
中的GetHashCode
和Equals
方法。
答案 3 :(得分:0)
当您使用SomeThings
和someEntity
之类的名称时,确实知道这一点有点棘手,但我相信正在发生的事情是当您查看someEntity.SomeThings
时,SomeThings
是Employee
个实体的集合。因此,lambda表达式中的t
将引用Employee
对象,使您能够比较它们的属性。
尝试以下
var something = someEntity.SomeThings.First(t => t.Equals(employee));
看看它是否更好。
编辑:实际上,.Equals()
语法优于我最初提出的==
...
EDIT2:正如Sessiz Saas所说,这可能是因为延迟加载。下面提供了另一种加载员工对象的方法:
var myThings = dataContext.Things.Include("employee");
但是,请记住,这可能会导致额外的(并且无论如何都可以完成工作)数据调用。