新问题
绕过房子后,我认为Except
不是问题所在。我认为从数据库中选择是错误的。因此,我提出了一个新问题Where returns wrong record。这个问题将被关闭 - 或者我会对另一个问题的回答进行修改。
我正在尝试将Linq Except()
方法与自定义比较器一起使用。我认为一切正常,因为我的数据集从2k记录大幅缩小到62.然而在剩下的62条记录中,我有一个副本(数据库中已经存在的项目),我不确定如何。
这是我在观察窗口中的重复条目:
类似地,数据库中的条目(PostcodeKey和Zone_ID是复合主键)
我只是应该在保存之前从我的收藏中删除数据库中已存在的任何项目(这是通过CSV导入):
IEnumerable<ZoneMapping> items // parameter passed in
// Exclude any items that we already have
items = items.Except(this.context.ZoneMappings.Include("Zone"), new ZoneMappingComparer()).ToList();
// Process all the items and save them
foreach (ZoneMapping item in items)
{
this.context.ZoneMappings.Add(item);
}
this.context.SaveChanges();
我已经验证了我的上下文中的数据库计数和ZoneMappings.Count()
与它们相同。我的比较器非常简单:
public class ZoneMappingComparer : IEqualityComparer<ZoneMapping>
{
/// <inheritdoc/>
public bool Equals(ZoneMapping x, ZoneMapping y)
{
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;
if (x.PostcodeKey == "2214" && y.PostcodeKey == "2214")
Debugger.Break();
// Compare the Postcode Key
int compareResult = x.PostcodeKey.CompareTo(y.PostcodeKey);
if (compareResult != 0)
return false;
// Compare the Zone
if (x.Zone == null && y.Zone == null)
return true;
// Compare the Zone
if (x.Zone == null || y.Zone == null)
return false;
compareResult = x.Zone.ID.CompareTo(y.Zone.ID);
return compareResult == 0;
}
/// <inheritdoc/>
public int GetHashCode(ZoneMapping obj)
{
return obj.PostcodeKey.GetHashCode() + ((obj.Zone != null) ? obj.Zone.ID.GetHashCode() : 0);
}
}
正如您所看到的那样,我已经在其中放置了一个Debugger.Break(),这会触发,并且方法compareResult
的末尾为0.
如果我继续执行直到保存但是我得到一个UpdateException并带有以下消息:
{“违反PRIMARY KEY约束'PK_dbo.NetC_EF_ZoneMapping'。无法在对象'dbo.NetC_EF_ZoneMapping'中插入重复键。重复键值为(2214,257)。\ r \ n语句已终止。”}
我是否误解了Except应该如何工作?或者我错过了其他明显的东西?
修改
我已经尝试过克里斯的建议,可能是红鲱鱼,但我已经切换到手动填充我的列表:
// Exclude any items that we already have
items = new List<ZoneMapping>() { new ZoneMapping() { PostcodeKey = "2214", Zone = new Zone() { ID = 257 } } };
items = items.Except(this.context.ZoneMappings.Include("Zone"), new ZoneMappingComparer()).ToList();
ZoneMapping mapping = this.context.ZoneMappings.Include("Zone").Where(z => z.PostcodeKey == "2214" && z.Zone.ID == 257).First();
var comparer = new ZoneMappingComparer();
if (comparer.Equals(items.ToList()[0], mapping))
{
Debugger.Break();
}
奇怪的是,从上下文来看,我的区域是错误的:
另一张图片说明了返回的错误记录和生成的SQL(看起来很好)。如果我对相同的影响运行自动化测试,它可以正常工作并返回正确的记录。
这是我的ZoneMapping类:
/// <summary>
/// Represents a mapping between a postcode and a zone
/// </summary>
[Table("NetC_EF_ZoneMapping")]
public class ZoneMapping
{
/// <summary>
/// Gets or sets the postcode identifier
/// </summary>
[Key]
public String PostcodeKey { get; set; }
/// <summary>
/// Gets or sets the Zone identifier
/// </summary>
[Key]
public Zone Zone { get; set; }
}
答案 0 :(得分:1)
在这种情况下,实际上使用Where子句更清楚地证明了问题。实际问题是由于PrimaryKey应用于实体而不是简单字段。有关详细信息,请参阅Where returns wrong record