Linq to SQL - 更新失败

7

我在更新Linq to SQL实体时遇到了一些问题。奇怪的是,我可以更新item实体的每个字段,除了name

这里是我编写的两个简单测试:

 [TestMethod]
        public void TestUpdateName( ) {
            using ( var context = new SimoneDataContext( ) ) {
                Item item = context.Items.First( );

                if ( item != null ) {
                    item.Name = "My New Name";
                    context.SubmitChanges( );
                }
            }
        }

        [TestMethod]
        public void TestUpdateMPN( ) {
            using ( var context = new SimoneDataContext( ) ) {
                Item item = context.Items.First( );

                if ( item != null ) {
                    item.MPN = "My New MPN";
                    context.SubmitChanges( );
                }
            }
        }

不幸的是,TestUpdateName() 出现以下错误:System.Data.SqlClient.SqlException: Incorrect syntax near the keyword 'WHERE'..

这是输出的 SQL:

UPDATE [dbo].[Items] SET WHERE ([Id] = @p0) AND ([CategoryId] = @p1) AND ([MPN] = @p2) AND ([Height] = @p3) AND ([Width] = @p4) AND ([Weight] = @p5) AND ([Length] = @p6) AND ([AdministrativeCost] = @p7) -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1] -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [1] -- @p2: Input VarChar (Size = 10; Prec = 0; Scale = 0) [My New MPN] -- @p3: Input Decimal (Size = 0; Prec = 5; Scale = 3) [30.000] -- @p4: Input Decimal (Size = 0; Prec = 5; Scale = 3) [10.000] -- @p5: Input Decimal (Size = 0; Prec = 5; Scale = 3) [40.000] -- @p6: Input Decimal (Size = 0; Prec = 5; Scale = 3) [30.000] -- @p7: Input Money (Size = 0; Prec = 19; Scale = 4) [350.0000] -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926

可以看到,没有生成任何更新(SET 为空...)我不知道为什么会出现这种情况。

还有提前说明一下...是的,表 Item 有一个 PK(Id)。谢谢

更新: 看起来错误是由于覆盖 GetHashcode() 导致的。 这是我的当前实现:

return string.Format( "{0}|{1}|{2}|{3}", Name, Id, UPC, AdministrativeCost).GetHashCode( );


如果您修改了“Name”和另一个属性,会发生什么?它会更新两个属性还是只更新另一个属性?此外,在生成的代码中,“Name”的setter是否会触发“PropertyChanged”事件?我认为,除非触发该事件,否则DataContext不会将其视为更改。 - Mike Two
如果我修改名称和另一个属性,只有另一个属性会改变。 - Isaac E
2个回答

12

听起来你的DBML可能不同步了。你应该删除表格,重新添加它们,然后再次运行。

只需手动删除Items表格,然后重新添加即可。

编辑: 根据你的编辑,你应该查看以下与GetHashCode相关的线程。

http://social.msdn.microsoft.com/forums/en-US/linqtosql/thread/6cc6c226-f718-4b22-baad-dba709afe74b/

.Net规则要求必须始终同时实现GetHashCode()和Equals()。两个相等的对象必须具有相同的哈希码。

此外,GetHashCode()+Equals()的组合形成实体的身份概念。如果将其基于字段值(而非PK)进行,则随着字段的更改,标识也会更改。如果L2S必须在基于实体的身份查找字典中查找其他信息,尤其是如果L2S需要在其身份缓存中查找实体,则这很糟糕!

建议:不要更改实体的身份。L2S希望它基于对象的自然(地址为基础的)身份。


刚刚手动删除了表格,但是没有起作用。我还尝试使用Hugati工具再次同步,但是仍然出现相同的错误。 - Isaac E
@Isaac TestUpdateMPN 能正常工作,只有 TestUpdateName 失败了吗?当数据库表的定义与模式不匹配时,会出现此错误。 - Kelsey
+1 for the GetHashCode() 的部分。那正是我的问题所在。我试图更改被 GetHashCode() 覆盖使用的字段。 - tandrewnichols

0

看起来生成的SQL语句没有包含SET子句中的内容(请注意在SET之后没有[Name] = @pXX)。在dbml设计器中,实体字段的所有属性(数据类型、大小等)是否都正确设置了?


我注意到了这一点,并在一分钟前编辑了帖子。 DBML上的属性似乎是正确的。我使用Hugati DBML工具来保持我的DBML模式与数据库同步。感谢您的回复。 - Isaac E
@Isaac:最新版本仍然反映了这个问题(它说“UPDATE [dbo].[Items] SET WHERE...”)。L2S没有生成要更新的列和与之对应的值的列表(你会期望它说“UPDATE [dbo].[Items] SET [Name] = @p0 WHERE...”或类似的内容)。 - Adam Robinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接