2011-11-11 70 views
0

给定像Person这样的简单类,并带有FirstName,LastName和DOB属性以及Id属性(它是主键)。如何防止首先使用EF代码的逻辑重复?

当我调用我的create action时,我想执行验证以确定我传入的模型是否与FirstName,LastName和DOB属性恰好匹配任何已存在的记录。在这种情况下,我想排除Id属性,因为进入应用程序的模型还没有,并会产生误报。

目前我只是用任何扩展方法是这样的...

if (!context.People.Any(x => x.FirstName == model.FirstName && x.LastName == 
model.LastName && x.DOB == model.DOB)) 

这肯定的作品,但完全是,好了,不优雅。

当然有更好的方法吗?

+0

您可能可以通过对数据库进行唯一约束来避免这种情况,然后在代码中进行适当的错误处理。如果你想在值持久化之前检查重复项,那么我认为'Any()',虽然不完全优雅,但是完全没问题。 –

+0

[最好的方法来检查对象是否存在于实体框架?](http://stackoverflow.com/questions/1802286/best-way-to-check-if-object-exists-in-entity-framework) –

+0

这不是重复的,你引用的问题的答案是我说我明确想避免的东西 – keithwarren7

回答

0

问题是你不希望直接在控制器中看到任何呼叫,或者你根本不喜欢该呼叫?

如果是前者,则使用验证框架来隐藏控制器的详细信息。如果是后者,则可以在数据库中创建某种存储过程/函数,然后调用它。

虽然我并不认为这段代码是坏的。我只是认为它需要一个验证。 FluentValidation对此非常好,但DataAnnotations也可以。

+0

我想真正的问题是,对Any的调用取决于在每个情况下写出每个非关键属性实体,而不是一个通用的调用。我想现在我可能会写一个扩展方法,它接受一个模型并匹配非关键属性的值。 所以底线,我可以问这个问题 - '我怎么能比这更懒惰...' – keithwarren7

+0

写这个扩展方法正是我正在努力回答你的问题。这似乎是最好的解决方案。你怎么能更懒惰?问问它,看看其他人是否会为你编写它) – Sorax

+1

@ keithwarren7 - 扩展方法将是一个坏主意,因为扩展方法是静态的。您不希望在扩展方法中查询数据库,因为它会在程序的整个生命周期中保持开放连接。 –

1

如果唯一性是一个业务需求,那么你应该在数据库中处理这个唯一的约束。然后,你不需要检查,数据库会抛出一个异常,并告诉你它何时被违反。您处理异常并告诉用户他们已经在系统中。

+0

我不同意这种做法。我认为使用验证器会更好。除了验证之外,您还可以拥有一个唯一的约束条件,但不应该期望发生这样的异常。只是我的意见,但。 – Dismissile

+0

我也不同意,这是一个非常不稳定的解决方案 - 应用程序通过异常的控制流程在我的坏代码属性列表中非常高。 – keithwarren7

+0

@ keithwarren7 - 这不是控制流。您没有使用例外来决定更新记录或插入记录。那会很糟糕。这是用户插入重复记录的情况。你唯一的选择是首先查询数据库,但你说你不想这样做。 –