LINQ to SQL 编译器似乎过度优化了内部包含其他类的类的默认类值。
下面是一些说明问题的示例代码:
void Main()
{
testInitialValueFromDB();
}
void testDefault()
{
using(DataContext db = new DataContext()) //in my actual code its GEMSDBDataContext where it got created from a .dbml file
{
var result = db.GEMSUsers.Take(10).Select(x=> new AllInfo {
info = new InitialInfo {
Test1 = x.username.Length
},
info2 = new SetAfterInfo {
Test2 = ""
}
}).ToList();
result[0].info2.Test2 = "Setting afterwards";
}
//from now on all the values in result say Setting afterwards
}
void testInitialValueFromDB()
{
using(DataContext db = new DataContext()) //in my actual code its GEMSDBDataContext where it got created from a .dbml file
{
var result = db.GEMSUsers.Take(10).Select(x=> new AllInfo {
info = new InitialInfo {
Test1 = x.username.Length
},
info2 = new SetAfterInfo {
Test2 = x.rowguid.ToString()
}
}).ToList();
result[0].info2.Test2 = "Setting afterwards";
}
//This actually works and only the first item is changed
}
void testGuid()
{
using(DataContext db = new DataContext()) //in my actual code its GEMSDBDataContext where it got created from a .dbml file
{
var result = db.GEMSUsers.Take(10).Select(x=> new AllInfo {
info = new InitialInfo {
Test1 = x.username.Length
},
info2 = new SetAfterInfo {
Test2 = System.Guid.NewGuid().ToString()
}
}).ToList();
//I would expect Test2 to be a new guid everytime but it's always the same, like the class got instantiated only once.
result[0].info2.Test2 = "Setting afterwards";
//again this changes for all the elements in the list
}
}
public class AllInfo
{
public InitialInfo info {get; set;}
public SetAfterInfo info2 {get; set;}
}
public class InitialInfo
{
public int Test1 {get; set;}
}
public class SetAfterInfo
{
public string Test2 {get; set;}
}
现在,如果您调用 testDefault() 或 testGuid(),似乎只初始化一次 SetAfterInfo,如果我更改任何元素的 Test2 属性,它会在列表中的每个项目中更新。
我遇到这个错误是因为我必须运行一个查询,但我必须以一种无法在 SQL 中表示的方式将属性设置为一个值,所以我在代码中调用 ToList() 之后才这样做.
唯一可行的方法是从数据库初始化 Test2,在这种情况下输出是预期的。
我只是好奇这是否是 LINQ to SQL 编译器中的合法错误。
更多信息:
.NET 框架 4.5 SQL 服务器 2012
最佳答案
从偏离规范的意义上讲,这不是错误,因为没有记录此查询的行为。 L2S(和 EF)没有记录很多事情。
但从某种意义上说,这是一个错误,团队可能会同意应该对此进行更改。
不幸的是,L2S 团队已不复存在。产品被放弃。不要指望修复。
作为变通方法引入人为依赖:
info2 = new SetAfterInfo {
Test2 = someStringColumn.Substring(0, 0) //empty string
}
L2S 将不再认为 info2
的初始值设定项是常量。本着这种精神,您可以使用任何其他人工依赖。例如,您可以将一列分配给虚拟属性。
关于C# LINQ To Sql 默认对象实例化过度优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29708777/