使用生成的 SQLMetal class 更新 table 时关键字 'WHERE' 附近的语法不正确
Incorrect syntax near the keyword 'WHERE' when updating table using SQLMetal generated class
我在 SQL 服务器中有一个非常基本的 table(双键,无外键)。我使用 SQLMetal 生成了映射代码。我还扩展了自动生成的部分 class,因此我可以实现 IEquatable。问题是,一旦我实施了 IEquatable,我就失去了使用 SQLMetal 生成的 classes 更新记录的能力。提交更改时出现以下异常:
Incorrect syntax near the keyword 'WHERE'
下面的示例代码说明了这个问题。它运行良好,直到实施 IEquatable:
var connection = "Your connection string";
var dbInsert = new DBTest(connection);
var recordToInsert = new TestTable()
{
PrimaryKey1 = 123,
PrimaryKey2 = "Red",
TheValue = Guid.NewGuid().ToString(),
};
dbInsert.TestTable.InsertOnSubmit(recordToInsert);
dbInsert.SubmitChanges();
var dbEdit = new DBTest(connection);
dbEdit.Log = Console.Out;
var ti1 = dbEdit.TestTable.Single(x => x.PrimaryKey1 == 123 && x.PrimaryKey2 == "Red");
ti1.TheValue = Guid.NewGuid().ToString();
dbEdit.SubmitChanges();
这是我对 IEqua 的实现table(由 ReSharper 自动生成):
public partial class TestTable : IEquatable<TestTable>
{
public bool Equals(TestTable other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _PrimaryKey1 == other._PrimaryKey1 && string.Equals(_PrimaryKey2, other._PrimaryKey2) && string.Equals(_TheValue, other._TheValue);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TestTable)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = _PrimaryKey1;
hashCode = (hashCode * 397) ^ (_PrimaryKey2 != null ? _PrimaryKey2.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (_TheValue != null ? _TheValue.GetHashCode() : 0);
return hashCode;
}
}
}
查看输出 window 中打印出的查询。 IEquatable实现时,SET子句为空(并导致抛出异常):
UPDATE [dbo].[TestTable]
SET
WHERE ([PrimaryKey1] = @p0) AND ([PrimaryKey2] = @p1) AND ([TheValue] = @p2)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [123]
-- @p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Red]
-- @p2: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [8dedfdca-84e9-4b7a-9268-4bbdde2e9ad2]
这是未实施 IEquatable 的相同输出:
UPDATE [dbo].[TestTable]
SET [TheValue] = @p3
WHERE ([PrimaryKey1] = @p0) AND ([PrimaryKey2] = @p1) AND ([TheValue] = @p2)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [123]
-- @p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Red]
-- @p2: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [8f6e72ee-f89e-40f3-830f-18e8b4b40f9e]
-- @p3: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [1ecaff9d-d460-4f3e-b35d-138ddeb2fb63]
这种行为是预期的吗?有办法解决吗?
事实证明,覆盖 GetHashCode() 方法会扰乱 DataContext 跟踪更改的能力。删除 GetHashCode 覆盖解决了这个问题。
我在 SQL 服务器中有一个非常基本的 table(双键,无外键)。我使用 SQLMetal 生成了映射代码。我还扩展了自动生成的部分 class,因此我可以实现 IEquatable。问题是,一旦我实施了 IEquatable,我就失去了使用 SQLMetal 生成的 classes 更新记录的能力。提交更改时出现以下异常:
Incorrect syntax near the keyword 'WHERE'
下面的示例代码说明了这个问题。它运行良好,直到实施 IEquatable:
var connection = "Your connection string";
var dbInsert = new DBTest(connection);
var recordToInsert = new TestTable()
{
PrimaryKey1 = 123,
PrimaryKey2 = "Red",
TheValue = Guid.NewGuid().ToString(),
};
dbInsert.TestTable.InsertOnSubmit(recordToInsert);
dbInsert.SubmitChanges();
var dbEdit = new DBTest(connection);
dbEdit.Log = Console.Out;
var ti1 = dbEdit.TestTable.Single(x => x.PrimaryKey1 == 123 && x.PrimaryKey2 == "Red");
ti1.TheValue = Guid.NewGuid().ToString();
dbEdit.SubmitChanges();
这是我对 IEqua 的实现table(由 ReSharper 自动生成):
public partial class TestTable : IEquatable<TestTable>
{
public bool Equals(TestTable other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _PrimaryKey1 == other._PrimaryKey1 && string.Equals(_PrimaryKey2, other._PrimaryKey2) && string.Equals(_TheValue, other._TheValue);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TestTable)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = _PrimaryKey1;
hashCode = (hashCode * 397) ^ (_PrimaryKey2 != null ? _PrimaryKey2.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (_TheValue != null ? _TheValue.GetHashCode() : 0);
return hashCode;
}
}
}
查看输出 window 中打印出的查询。 IEquatable实现时,SET子句为空(并导致抛出异常):
UPDATE [dbo].[TestTable]
SET
WHERE ([PrimaryKey1] = @p0) AND ([PrimaryKey2] = @p1) AND ([TheValue] = @p2)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [123]
-- @p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Red]
-- @p2: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [8dedfdca-84e9-4b7a-9268-4bbdde2e9ad2]
这是未实施 IEquatable 的相同输出:
UPDATE [dbo].[TestTable]
SET [TheValue] = @p3
WHERE ([PrimaryKey1] = @p0) AND ([PrimaryKey2] = @p1) AND ([TheValue] = @p2)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [123]
-- @p1: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Red]
-- @p2: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [8f6e72ee-f89e-40f3-830f-18e8b4b40f9e]
-- @p3: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [1ecaff9d-d460-4f3e-b35d-138ddeb2fb63]
这种行为是预期的吗?有办法解决吗?
事实证明,覆盖 GetHashCode() 方法会扰乱 DataContext 跟踪更改的能力。删除 GetHashCode 覆盖解决了这个问题。