ICollection<>。包含在EF中作为HashSet失败

时间:2014-02-14 02:46:28

标签: c# entity-framework hashset iequalitycomparer

我有一个如下定义的对象:

public  class QuestionSetAssignee
{
    [Required]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<QuestionSet> QuestionSets { get; set; }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    public override bool Equals(Object obj)
    {
        if (obj == null)
        {
            return false;
        }

        QuestionSetAssignee qsa = obj as QuestionSetAssignee;

        return Id == qsa.Id;
    }
}

以下声明:

QuestionSetAssignees.Contains(director)

public bool isEditable()
{
    ApplicationDbContext db = new ApplicationDbContext();
    QuestionSetAssignee director = db.QuestionSetAssignees.Find((int)QuestionSetAssigneeEnum.Director);

    if (Conference.AcceptingDirectorApplications && QuestionSetAssignees.Contains(director))
    {
        return false;
    }

    return true;
}

返回false,据我所知,应该返回true。 (注意:Conference.AcceptingDirectorApplications返回true)

如果不能立即清除,则导向器对象和HashSet对象作为DynamicProxies(由于EF和对象层次结构)而来。

这是导演对象:

enter image description here
(点击查看大图)

这里是QuestionSetAssignees对象:

enter image description here
(点击查看大图)

由于它是由EF 6提供的,我无法控制QuestionSetAsignees的类型(它在模型中被声明为ICollection。这也意味着我无法提供比较对象(就我所知而言)我想做的就是能够比较两个QuestionSetAsignee对象。我也尝试过实现IEquatable,但是没有用。

1 个答案:

答案 0 :(得分:1)

问题是它将您的Contains()转换为SQL调用,因此无论您放入EqualsGetHashCode(),它都无关紧要因为您要连接的数据库不使用它们来测试相等性(这就是"This" == "this"在数据库中使用实体框架时将返回true的原因,而数据库的排序规则不区分大小写。)

修复它的“快速而肮脏”的方法是在内存中实现集合,然后执行.Contains

QuestionSetAssignees.AsEnumerable().Contains(director))

但这不会给你很好的表现。您可能需要以不同的方式处理此查询,以便SQL的行为与您希望的一样。

我认为以下内容可能有效,但请测试一下,如果没有,请告诉我,我会将其删除。

QuestionSetAssignees.Select(assignee => assignee.Id).Contains(director.Id)