针对数据库的 EF 模型验证
本文关键字:模型 验证 EF 数据库 | 更新日期: 2023-09-27 18:35:33
我想使用 EF 5 模型验证来避免数据库中的重复值,所以我使用如下模型类:
[Table("MeasureUnits")]
public class MeasureUnit : IValidatableObject
{
public int MeasureUnitId { get; set; }
public string Symbol { get; set; }
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
using (MeasureUnitRepository rep = new MeasureUnitRepository())
{
MeasureUnit measureUnit = rep.FindDuplicateBySymbol(this);
if (measureUnit != null)
yield return new ValidationResult(
"There is another unit with this symbol, you can't duplicate it",
new[] { "Symbol" });
}
}
存储库类创建 DbContext,实现 IDisposable,具有查找副本的逻辑,并且一切都按预期工作。
但是,使用调试器,我意识到每次插入或更新都会执行两次验证,因此存储库(和 DbContext)也会实例化和处置两次。
除此之外,控制器中还有另一个 DbContext,但除了在模型的构造函数中包含 DbContext 之外,只是找不到在模型类中使用它的方法,但我觉得这不是正确的解决方案。
有没有更好的"正确"方法来实现这种验证?
提前谢谢。
当你必须去数据库时,你需要使用DbContext
,DbContext
有一个叫做ValidateEntity
的可覆盖方法。请参阅本文:实体框架验证。
把我使用的代码放在另一个答案中
更多关于我如何在 MVC 中构建验证的信息 这里.
此外,在存储库中实例化上下文可能会让您感到悲伤。存储库需要共享上下文。您可以将上下文视为您的工作单元,并将其传递到构造函数中的存储库中,或者您可以将上下文包装在您自己的工作单元中并将其传入。
您可以使用任何可用的IOC容器(如Unity,Ninject,Autofac或StructureMap)将存储库注入为依赖项。
这样,您将能够访问控制器、Validate 方法或需要使用它的任何位置中的同一对象。
其中一些 IOC(肯定是 Ninject - 寻找"请求范围")容器能够与 MVC 集成 ASP.NET 以便每个请求创建一次依赖项(在这种情况下是您的存储库)并在请求结束时释放。
使用Ninject的示例:
您创建一个全局可访问(设计取决于您)的 nin注入内核
public static class NinjectKernel
{
public static IKernel Kernel = new StandardKernel();
static NinjectKernel()
{
Kernel.Bind<IMyRepository>().To<MyRepositoryImpl>().InRequestScope();
}
}
以及用于 MVC 控制器的控制器工厂
public class NinjectControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext,
Type controllerType)
{
return controllerType == null ? null : (IController)NinjectKernel.Kernel.Get(controllerType);
}
}
然后,您可以在 Global.asax 中像这样设置控制器工厂
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
,并以与在控制器工厂中类似的方式在验证方法中获取存储库。