问题描述
我正在尝试使EF 4.1与存储库,UnitOfWork,将实体与EF分离以及进行验证有关.
I'm trying to get EF 4.1 working with Repository, UnitOfWork, separation of entities from EF and validation.
我遵循了此指南可以很好地将我的POCO实体与EF模型区分开来,我现在正在按照此指南(使用IValidatableObject)实现验证.
I followed this guide to get a nice separation of my POCO entities from the EF model and I'm now following this guide to implement validation (with IValidatableObject).
我的解决方案包括:
- Contacts.Repository [引用EF和Contacts.Entities]:
- Contacts.edmx
- ContactsDbContext.cs
- Contacts.Repository [references EF and Contacts.Entities]:
- Contacts.edmx
- ContactsDbContext.cs
- Contact.cs(Contacts.Entities.Contact局部类)
- Contact.cs(Contacts.Entities.Contact局部类)
但是我正在通过验证碰到一堵砖墙:
But I'm hitting a brick wall with the validation:
- 我无法向Contacts.Entities添加验证逻辑,因为这会导致对Contacts.Repository进行循环引用(contact.Validate(...)需要使用ContactsDbContext).因此,我创建了一个单独的Contacts.Validation项目.
- 但是,这意味着将Contact类分为部分类,以在Contacts.Entities和Contacts.Validation中定义Contact.该代码不再编译,因为您无法跨不同的程序集定义局部类.
有人在这里给我指点吗?我已经在下面发布了代码...
Anyone got any pointers for me here? I've posted the code below...
Contacts.Repository.ContactsDbContext.cs:
Contacts.Repository.ContactsDbContext.cs:
namespace Contacts.Repository { public partial class ContactsDbContext : DbContext { public DbSet<Contact> Contacts { get; set; } protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items) { items.Add("Context", this); return base.ValidateEntity(entityEntry, items); } } }
Contacts.Entities.Contact.cs:
Contacts.Entities.Contact.cs:
namespace Contacts.Entities { public partial class Contact { public string Name { get; set; } } }
Contacts.Validation.Contact.cs包含:
Contacts.Validation.Contact.cs contains:
namespace Contacts.Entities { public partial class Contact : IValidatableObject { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { ContactsDbContext contacts = (ContactsDbContext)validationContext.Items["Context"]; //Check if Contact already exists with the same Name if (contacts.Any<Contact>(c => c.Name == this.Name)) yield return new ValidationResult("Contact 'Name' is already in use.", new string[] { "Name" }); yield break; } }
推荐答案
技术上,您可以引入具有如下所示的显式实现的接口:
Technically you could introduce an interface with an explicit implementation like so:
在 Contacts.Entities 程序集中:
public interface IContactsDbContext { IQueryable<Contact> Contacts { get; } // Not DbSet<Contact> because you don't want dependency on EF assembly } //... public class Contact : IValidatableObject // No partial class anymore { public string Name { get; set; } public IEnumerable<ValidationResult> Validate( ValidationContext validationContext) { IContactsDbContext context = validationContext.Items["Context"] as IContactsDbContext; if (context.Contacts.Any<Contact>(c => c.Name == this.Name)) yield return new ValidationResult( "Contact 'Name' is already in use.", new string[] { "Name" }); yield break; } // IValidatableObject, ValidationResult and ValidationContext is in // System.ComponentModel.DataAnnotations.dll, so no dependency on EF }
在 Contacts.Repository 程序集中(引用 Contacts.Entities 程序集):
In Contacts.Repository assembly (references Contacts.Entities assembly):
public class ContactsDbContext : DbContext, IContactsDbContext { public DbSet<Contact> Contacts { get; set; } IQueryable<Contact> IContactsDbContext.Contacts // explicit impl. { get { return Contacts; } // works because DbSet is an IQueryable } protected override DbEntityValidationResult ValidateEntity( DbEntityEntry entityEntry, IDictionary<object, object> items) { items.Add("Context", this); return base.ValidateEntity(entityEntry, items); } }
可以删除
Contacts.Validation 程序集.
但是,我不太喜欢这种解决方案.通过
Validate
方法,您的POCO仍然依赖于存储库(无论是否存在接口).为了更好地分离关注点,我可能希望拥有一个单独的Validation类,该类也可能对存储库进行操作.或者,如果我要实现IValidatableObject
,我可能只会进行仅依赖于模型对象属性的验证(例如生产日期一定不能晚于发货日期"之类的东西).好吧,这只是部分品味问题.您链接的第二个示例并不真正关心关注点的分离,因此您与第一个示例存在某种冲突.However, I do not really like this solution. Your POCO has - through the
Validate
method - still a dependency on the repository, if interface or not. For a stronger separation of concerns I would probably prefer to have a separate Validation class which does perhaps also operations on the repo. Or if I would implementIValidatableObject
I would probably only do validations which depend on model object properties alone (things like "production date must not be later than shipping date" and so on). Well, it's partially a matter of taste. The second example you have linked does not really care about separation of concerns, so you have somehow a conflict with the first example.这篇关于实体框架IValidatableObject参考DbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!