【问题标题】:How to create Value-Objects in ASP.Net MVC, Entity Framework 6 project?如何在 ASP.Net MVC、Entity Framework 6 项目中创建值对象?
【发布时间】:2017-02-19 17:28:10
【问题描述】:

我的测试应用中有类:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
        Database.SetInitializer<ApplicationDbContext>(new MovieContextInitializer());
    }

    public DbSet<Movie> Movies { get; set; }
    public DbSet<Currency> Currencies { get; set; }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Types<Movie>()
        .Configure(ctc => ctc.Property(m => m.Price.Amount).HasColumnName("MoviePriceAmount"));

        modelBuilder.Types<Movie>()
        .Configure(ctc => ctc.Property(m => m.Price.Currency.Id).HasColumnName("MoviePriceCurrency"));

        base.OnModelCreating(modelBuilder);
    }
}

用于初始化数据的MovieContextInitializer:

public class MovieContextInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
    protected override void Seed(ApplicationDbContext context)
    {
        var usdCurrency = new Currency {Id = 1, Name = "USD"};
        var euroCurrency = new Currency {Id = 2, Name = "EUR"};

        context.Currencies.Add(usdCurrency);
        context.Currencies.Add(euroCurrency);

        context.Movies.Add(new Movie
        {
            Title = "GhoustBusters",
            Genre = "Comedy",
            ReleaseDate = new DateTime(2016, 9, 10),
            Price = new Money(50, usdCurrency)
        });

        context.Movies.Add(new Movie
        {
            Title = "Matrix",
            Genre = "Action",
            ReleaseDate = new DateTime(2010, 2, 10),
            Price = new Money(40, euroCurrency)
        });
    }
}

还有我的实体和值对象类:

public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public Money Price { get; set; }
}
public class Currency
{
    public int Id { get; set; }
    public string Name { get; set; }
}
[ComplexType]
public class Money 
{
    public Money(int amount, Currency currency)
    {
        Amount = amount;
        Currency = currency;
    }
    public int Amount { get; private set; }
    public Currency Currency { get; private set; }
}

当我试图打电话时:

ApplicationDbContext db = new ApplicationDbContext();
var movies = db.Movies.ToList() 

我收到异常:“在模型生成期间检测到一个或多个验证错误:DomainDrivenWeb.Models.Currency:名称:模式中的每个类型名称必须是唯一的。类型名称“货币”已定义。 ”。

【问题讨论】:

  • public Currency Currency { get; private set; } 请尝试在此处使用不同的变量名,例如public Currency _currency { get; private set; } 或除Currency 之外的任何其他名称。
  • 答案在错误信息中。
  • 我更改了货币 Currency { get;私人套装; } to Currency AmountCurrency { get;私人套装; },但得到了同样的例外。

标签: c# asp.net-mvc entity-framework domain-driven-design value-objects


【解决方案1】:

这里的问题是您将Currency 视为一个值对象和一个实体。

这一行:

modelBuilder.Types<Movie>()
    .Configure(ctc => ctc.Property(m => m.Price.Currency.Id).HasColumnName("MoviePriceCurrency"));

告诉 EF Currency 类型隐式是 Move 实体上的复杂类型 - 嵌套在 Price 属性(Money 类型)上。这更像是一个 ValueObject。

但是

public DbSet<Currency> Currencies { get; set; }

告诉 EF 将其视为实体。

这就是错误消息显示 Each type name in a schema must be unique. Type name 'Currency' is already defined. 的原因 - 当需要将货币模型设置为实体时,类型名称货币已在 Movie 实体上定义为复杂类型。

如果您删除这些配置行中的一个或另一个,错误应该会消失 - 但它不会真正解决您的问题,因为您需要考虑 - 在您的域中 Currency 是真正的实体还是值对象?

Movie 有一个Price 类型为Money,它有一个类型为Currency 的属性——这种用法意味着它是一个ValueObject。但是该类有一个 Id 字段 - 'identity' 的存在意味着它是一个实体。

您需要仔细考虑这些类型中包含的域建模和业务流程,以探索应该如何真正对待它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 2016-05-15
    • 2017-07-13
    • 1970-01-01
    相关资源
    最近更新 更多