gpt4 book ai didi

validation - Entity Framework IValidatableObject 引用 DbContext

转载 作者:行者123 更新时间:2023-12-04 11:14:26 24 4
gpt4 key购买 nike

我试图让 EF 4.1 与 Repository、UnitOfWork、EF 实体分离和验证一起工作。

我关注了this将我的 POCO 实体与 EF 模型很好分离的指南,我现在正在关注 this实现验证的指南(使用 IValidatableObject)。

我的解决方案包括:

  • Contacts.Repository [引用 EF 和 Contacts.Entities]:
  • Contacts.edmx
  • 联系人DbContext.cs
  • Contacts.Entities [无引用]:
  • Contact.cs(Contacts.Entities.Contact 部分类)
  • Contacts.Validation [引用 Contacts.Entities 和 Contacts.Repository]
  • Contact.cs(Contacts.Entities.Contact 部分类)

  • 但是我在验证中遇到了障碍:
  • 我无法向 Contacts.Entities 添加验证逻辑,因为它会导致使用 Contacts.Repository 进行循环引用(contact.Validate(...) 需要使用 ContactsDbContext)。所以我创建了一个单独的 Contacts.Validation 项目。
  • 但是,这意味着将 Contact 类与部分类分开,以在 Contacts.Entities 和 Contacts.Validation 中定义 Contact。代码不再编译,因为您无法跨不同的程序集定义分部类。

  • 有人在这里给我指点吗?我已经在下面发布了代码...

    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:
    namespace Contacts.Entities
    {
    public partial class Contact
    {
    public string Name { get; set; }
    }
    }

    Contacts.Validation.Contact.cs 包含:
    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;
    }
    }

    最佳答案

    从技术上讲,您可以引入一个具有显式实现的接口(interface),如下所示:

    联系人.实体 部件:

    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 程序集):
    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 组件可以被删除。

    但是,我不太喜欢这种解决方案。您的 POCO - 通过 Validate方法 - 仍然依赖于存储库,如果接口(interface)与否。为了更好地分离关注点,我可能更喜欢有一个单独的 Validation 类,它可能也对 repo 进行操作。或者,如果我实现 IValidatableObject我可能只会进行仅依赖于模型对象属性的验证(例如“生产日期不得晚于发货日期”等)。嗯,这部分是口味问题。您链接的第二个示例并不真正关心关注点分离,因此您与第一个示例存在某种冲突。

    关于validation - Entity Framework IValidatableObject 引用 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6495157/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com