使用实体框架代码优先我是否需要让我的域模型贫血?

Aca*_*uza 9 .net domain-driven-design entity-framework

与实体框架代码 - 首先我必须公开所有属性来生成数据库,这意味着使用实体框架代码优先方法我被迫有一个贫穷的领域与丰富的模型混合?因为不需要公开的属性,必须是.

例如:

使用丰富的模型,实体框架中的这将不起作用:

public class Car
{
    private int _actualPosition;

    public void Accelerate()
    {
        this._actualPosition += 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了工作,我们需要_actualPosition公开:

public class Car
{
    public int ActualPosition { get; set; }

    public void Accelerate()
    {
        this.ActualPosition += 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在实体IMO是丑陋的,因为我有一个方法在属性中添加+ 10并同时公开它,我不希望该属性是公共的.

另一个例子:

想象一下,我想要一个多对多的关系,但只有一种方式:

public class User
{
   public long Id { get; set; }

   public string Name { get; set; }

   public IList<Role> Roles { get; set; }
}

public class Role
{
   public long Id { get; set; }

   public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我如何与该模型建立多对多的关系?据我所知,我不可能做双向关系:

public class User
{
   public long Id { get; set; }

   public string Name { get; set; }

   public IList<Role> Roles { get; set; }
}

public class Role
{
   public long Id { get; set; }

   public string Name { get; set; }

   public IList<User> Users { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

通过这个模型,我将能够建立多对多的关系:

modelBuilder.Entity<User>()
                .HasMany(x => x.Roles)
                .WithMany(y => y.Users);
Run Code Online (Sandbox Code Playgroud)

我是正确的?如果是,实体框架并不令我满意.

"又如"与回答工作@Slauma:

modelBuilder.Entity<User>()
            .HasMany(x => x.Roles)
            .WithMany()
            .Map(a =>
            {
                a.MapLeftKey("UserId");
                a.MapRightKey("RoleId");
                a.ToTable("UserRoles");
            });
Run Code Online (Sandbox Code Playgroud)

Ste*_*eve 1

简短的回答:除非框架支持它,否则如果您尝试同时使用业务规则和公共属性,那么您将无法在此类中塞入太多内容。

长答案: 我曾经使用过一个非常像这样的系统,基本上我意识到测试和封装的最佳方法是用我真正的域类包装这个类。

public class Car
{
    private CarPersistence _carPersistence;

    public void Accelerate()
    {
        this._carPersistence.ActualPosition += 10; 
    }

    public Car (CarPersistence car) {
        _carPersistence = car;
    }
}

public class CarPersistence
{
    public int ActualPosition;
}
Run Code Online (Sandbox Code Playgroud)

当我之前这样做时,我能够让较低级别的持久性类实现一个接口,我的测试可以使用该接口注入业务类以进行简单的测试,无需与数据库通信。

像这样的系统,您的业务类位于一个“层”,而您的持久性类位于另一“层”,您可以很容易地建立一对多关系,只需将其构建到从持久性构建业务类的任何内容中即可课程:

public class User
{
   private UserPersistence _user;
   private IList<Persistence> _roles;

   public User (UserPersistence user, IList<Persistence> roles) {
       _user = user;
       _roles = roles;
   }
}
Run Code Online (Sandbox Code Playgroud)

抱歉,语法可能不完美,这是我能记得的从 VB 音译到 C# 的最好结果;)