6

这很奇怪......之前完成了很多次更新,但无法发现为什么会有所不同。虽然我现在使用的是 .net 4.0 - 但我怀疑它是 L2S 实现中的一个错误。它不像这样是它的一个奇怪而美妙的应用。虽然我相当确定这段代码在我使用 RC 时有效。

我还设法通过使用以下信息从头开始构建项目来重现此错误。

这里的问题是L2S生成的update语句在set语句中没有字段。我已经尝试检查 pk 是否已设置(我认为 where 需要每个字段的唯一原因)并且还阅读了其他 dbml 属性。我已经使用 linq2Sql 大约 1 年了,从来没有遇到过问题......我仍然认为我只是有一个巨大的大脑放屁。

注意:我已经清理了 equals 和 GetHashCode 方法以删除一些字段 - 在此之后问题仍然存在。我还没有清理 SQL。

我有一个来自 dbml 的客户端类我添加了一个名为 update 的方法

public partial class Client :  ICopyToMe<Client>

CopyToMe 方法继承自一个接口

   public  interface ICopyToMe<T>
    {
        void CopyToMe(T theObject);
    }

该类也覆盖了 getHashCode

public override int GetHashCode()
{
    int retVal = 13 ^ ID ^ name.GetHashCode();
    return retVal;
}

和等于

public override bool Equals(object obj)
{
    bool retVal = false;
    Client c = obj as Client;
    if (c != null)
        if (c.ID == this.ID && c._name == this._name)
            retVal = true;
    return retVal;
} 

部分类中的更新方法

 public void UpdateSingle()
        {          
            L2SDataContext dc = new L2SDataContext();
            Client c = dc.Clients.Single<Client>(p => p.ID == this.ID);
            c.CopyToMe(this);
            c.updatedOn = DateTime.Now;

            dc.SubmitChanges();
            dc.Dispose();
                        }

CopytoMe 方法

 public void CopyToMe(Client theObject)
        {
            ID = theObject.ID;
            name = theObject.name;                
        }

我选择了一个客户端,更改其名称,然后调用此更新方法。生成的sql如下

exec sp_executesql N'UPDATE [dbo].[tblClient]
SET 
WHERE ([ID] = @p0) AND ([name] = @p1) AND ([insertedOn] = @p2) AND ([insertedBy] = @p3) AND ([updatedOn] = @p4) AND ([updatedBy] = @p5) 
AND ([deletedOn] IS NULL) AND ([deletedBy] IS NULL) AND (NOT ([deleted] = 1))',N'@p0 int,@p1 varchar(8000),@p2 datetime,@p3 int,@p4 
datetime,@p5 int',@p0=103,@p1='UnitTestClient',@p2=''2010-05-17 11:33:22:520'',@p3=3,@p4=''2010-05-17 11:33:22:520'',@p5=3

我不知道为什么这不起作用......使用了这种

选择对象 -> 将字段设置为新值 -> 提交所选对象

模式多次,没有这个问题。dbml 也没有明显的问题——尽管这可能是一个错误的陈述

有任何想法吗?

这个问题让我看起来像我将不得不回到 ADO.Net 这会让我很难过。

4

2 回答 2

1

好的,在与一些非常有帮助的微软人员讨论之后,我找到了这个问题的答案。

Linq 使用哈希代码在哈希表中索引其集合。这意味着哈希码函数只需要对唯一标识对象的字段起作用。

在这种情况下,哈希只能在 ID 列上起作用。因此 GetHashCode 将始终为具有相同主键的记录返回相同的值,即使它们的数据不同。

另一方面,Equals 可以测试更多的字段 - 即它的测试比 GetHashCode 比较更具体。

如果你让 GetHashCode 函数覆盖比主键更多的字段,那么 linq2sql 将失去对对象的跟踪,因此行为会非常奇怪。

于 2010-05-20T09:45:10.980 回答
0

如果将确切的 UPDATE 语句发送到数据库(没有任何 SET 参数),那么您在 LINQ to SQL 中发现了一个错误。在 .NET 4.0 中尝试您的代码,如果仍然失败,请向 Microsoft 连接站点提交错误。

于 2010-05-17T11:27:51.773 回答