我有检查的方案
1)如果来自empDb
的{{1}}中的任何道具(EmployeeObject)返回empXml
。否则返回true
false
所以让我直截了当,我正在尝试确定列表public class EmployeeObject
{
public Int32 Id { get; set; }
public string Title { get; set; }
public string Desc { get; set; }
.....
}
IList<EmployeeObject> empDb = PopulateFromDb(); //calling ado.net
IList<EmployeeObject> empXml = PopulateFromXml(); //deserializing xml
是否是列表empXml
的子集?
到目前为止已经尝试过;但即使我已经检查了两个列表中的数据,它也会返回false,除非我在表达式中做错了,否则它应该返回true。
empDb
或
//at least one MATCH
empDb.Any(a => empXml.Contains(a));
答案 0 :(得分:3)
如果您没有在Equals
课程中实施GetHashCode
和EmployeeObject
,那么将通过引用对员工进行比较。你肯定会在这里有不同的实例,因为当你从数据库中读取数据时会创建第一个列表,而当你反序列化xml时会创建第二个列表。因此,即使具有相同所有字段值的员工也会被视为不同。
如果您只想按员工ID检查匹配项,那么您可以将序列投影到ID,然后使用Intersect检查是否存在匹配
// at least one employee with equal Id
empDb.Select(e => e.Id).Intersect(empXml.Select(e => e.Id)).Any()
如果您想按字段值而不是引用来比较员工,您有几种选择。如果您不能或不想更改EmployeeObject类的实现并覆盖其Equals和GetHashCode方法,那么您可以为员工创建自定义 comparer :
public class EmployeeComparer : IEqualityComparer<EmployeeObject>
{
public bool Equals(EmployeeObject x, EmployeeObject y)
{
return x.Id == y.Id
&& x.Title == y.Title
&& x.Desc == y.Desc;
}
public int GetHashCode(EmployeeObject obj)
{
int code = 19;
code = code * 23 + obj.Id.GetHashCode();
code = code * 23 + obj.Title.GetHashCode();
code = code * 23 + obj.Desc.GetHashCode();
return code;
}
}
然后你可以使用这个比较器:
empDb.Intersect(empXml, new EmployeeComparer()).Any()
或者您可以将员工投射到匿名对象(其默认实现为Equals和GetHashCode):
empDb.Select(e => new { e.Id, e.Title, e.Desc })
.Intersect(empXml.Select(e => new { e.Id, e.Title, e.Desc })).Any()
或覆盖这些方法:
public class EmployeeObject
{
public Int32 Id { get; set; }
public string Title { get; set; }
public string Desc { get; set; }
public override int GetHashCode()
{
int code = 19;
code = code * 23 + Id.GetHashCode();
code = code * 23 + Title.GetHashCode();
code = code * 23 + Desc.GetHashCode();
return code;
}
public override bool Equals(object obj)
{
EmployeeObject other = obj as EmployeeObject;
if (other == null)
return false;
if (ReferenceEquals(this, other))
return true;
return Id == other.Id &&
Title == other.Title && Desc == other.Desc;
}
}
您的代码将有效。或者您可以使用Intersect:
empDb.Intersect(empXml).Any()
答案 1 :(得分:2)
如果Id
是您可能要写的实体的主键:
var set = new HashSet<int>(empXml.Select(x => x.Id)); //For faster lookup
empDb.Any(a => set.Contains(a.Id));
但是,如果您需要匹配所有属性,则需要覆盖Equals
和GetHashCode
。
(此实现也匹配属性的空值)
public class EmployeeObject : IEquatable<EmployeeObject>
{
public bool Equals(EmployeeObject other)
{
return Id == other.Id &&
string.Equals(Title, other.Title) &&
string.Equals(Desc, other.Desc);
}
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((EmployeeObject) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = Id;
hashCode = (hashCode*397) ^ (Title != null ? Title.GetHashCode() : 0);
hashCode = (hashCode*397) ^ (Desc != null ? Desc.GetHashCode() : 0);
return hashCode;
}
}
public Int32 Id { get; set; }
public string Title { get; set; }
public string Desc { get; set; }
}
写道:
var set = new HashSet<EmployeeObject>(empXml); //For faster lookup
empDb.Any(a => set.Contains(a));