C#:比较两个Linq2Sql实体不工作?

时间:2009-02-12 13:15:03

标签: c# linq-to-sql

有人能解释为什么这不起作用吗?

在数据库中,我们有一个带有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 ...

4 个答案:

答案 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);

生成类似

的Sql
SELECT ... 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中的GetHashCodeEquals方法。

答案 3 :(得分:0)

当您使用SomeThingssomeEntity之类的名称时,确实知道这一点有点棘手,但我相信正在发生的事情是当您查看someEntity.SomeThings时,SomeThingsEmployee个实体的集合。因此,lambda表达式中的t将引用Employee对象,使您能够比较它们的属性。

尝试以下

var something = someEntity.SomeThings.First(t => t.Equals(employee));

看看它是否更好。

编辑:实际上,.Equals()语法优于我最初提出的== ...


EDIT2:正如Sessiz Saas所说,这可能是因为延迟加载。下面提供了另一种加载员工对象的方法:

var myThings = dataContext.Things.Include("employee");

但是,请记住,这可能会导致额外的(并且无论如何都可以完成工作)数据调用。