在DbSet中查找对象是否存在

6

我有一个DbSet<ShippingInformation> ShippingInformations;对象,我还重写了equals运算符以用于ShippingInformation。

如何查找集合ShippingInformations中是否存在一个与类型为ShippingInformation的对象x相等的现有对象y。

到目前为止,我尝试过:

storeDB.ShippingInformations.Contains(shippingInformation);

然而,这仅适用于原始类型。

3个回答

9

很遗憾,您不能在EF查询中使用 Equals 实现,因为它无法反编译您的代码以查看其执行方式。您可以使用带有谓词表达式的 Any 方法来完成相同的操作:

bool exists = storeDB.ShippingInformations
    .Any(info =>
            info.CustomerID == other.CustomerID
            && info.CountryID == other.CountryID
        );

我编造了一些字段只是为了说明这个想法,other就是你要寻找的ShippingInformation
如果有很多地方需要重复使用此表达式,您可能希望使用LinqKit来组合表达式。
private static Expression<Func<ShippingInformation, ShippingInformation, bool>>
    isEqualExpr =
        (info, other) =>
            info.CustomerID == other.CustomerID
            && info.CountryID == other.CountryID;


// somewhere down this class

var expr = isEqualExpr; // reference the expression locally (required for LinqKit)
bool exists = storeDB.ShippingInformations
                  .Any(x => expr.Invoke(x, other)); // "injects" equality expression

这段代码应该放在数据层中。

但我并不能百分之百确定上面的代码是否可行。 可能实体框架不允许在查询表达式中使用“其他”对象。如果是这种情况(请告诉我),那么您需要修改表达式以接受所有基本类型值进行比较(在我们的示例中,它会变成Expression<Func<ShippingInformation, int, int, bool>>)。


如果我有十个字段要比较,是否有更简洁的方法来完成,而不是将它们全部放在一个表达式中? - Seth
这个会在多个地方使用吗?因为如果不是的话,只需要一个查询就很整洁(我认为)。你可以将其声明为静态字段并预先编译,这样它的性能会更好。 - Dan Abramov
很可能不止一个地方。你说的“将其声明为静态字段”是什么意思?你是指将执行比较的方法声明为静态方法并指向它吗? - Seth

1
bool ifExists = storeDB.ShippingInformations.Any(shi=>shi.Id == objectYouWantToCompareTo.Id);

如果你重载了等于运算符,这个方法也应该可以工作。

bool ifExists = storeDB.ShippingInformations.Any(shi=>shi == objectYouWantToCompareTo);

这不仅仅是在比较对象ID吗? - Seth
1
你可以比较任何东西,这里的Ids只是一个例子。 - AD.Net
第二个例子将无法工作,因为Entity Framework必须反编译您的Equals实现以查看其如何完成(当然它不会这样做)。此外,您甚至没有在此处调用Equals==默认比较引用,除非重写)。 - Dan Abramov
@Dan,你认为我该怎么做呢?我不想仅仅比较ID。我必须逐个比较每个元素吗,而不是使用“Equals”方法? - Seth
我不知道为什么会有这么多关于重写运算符和Equals方法的讨论。只需构建一个谓词到Any,以匹配您要查找的实体的主键即可。答案的第一部分是一个很好的方法。 - RPM1984
显示剩余2条评论

0

试试这个:

storeDB.ShippingInformations.ToList().Contains(shippingInformation);

你可能还需要实现一个IEqualityComparer来获得你想要的结果。


2
这将从数据库中获取整个“ShippingInformations”表。 - Dan Abramov
1
此外,实现 IEqualityComparer 对 Entity Framework 查询没有任何好处(假设您不会真的将整个表加载到内存中,然后对其执行 LINQ to Objects)。 - Dan Abramov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接