0

There are classes in my test applications:

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 for init data:

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)
        });
    }
}

And my entity and value objects classes:

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; }
}

When I am trying to call:

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

I am getting exception: "One or more validation errors were detected during model generation: DomainDrivenWeb.Models.Currency: Name: Each type name in a schema must be unique. Type name 'Currency' is already defined.".

Oblomingo
  • 668
  • 3
  • 10
  • 29
  • `public Currency Currency { get; private set; }` Please try using a different variable name here, such as `public Currency _currency { get; private set; }` or anything else except `Currency`. – Keyur PATEL Oct 11 '16 at 07:57
  • The answer is in the error message. – Peter Smith Oct 11 '16 at 07:57
  • I changed Currency Currency { get; private set; } to Currency AmountCurrency { get; private set; }, but got the same exception. – Oblomingo Oct 11 '16 at 08:06

1 Answers1

2

The problem here is that you're treating Currency as both a ValueObject and an Entity.

This line:

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

Tells EF that the Currency type is implicitly a Complex Type on the Move entity - nested on the Price property (of type Money). This is more like a ValueObject.

But

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

Tells EF to treat it as an Entity.

This is why the error message says Each type name in a schema must be unique. Type name 'Currency' is already defined. - When it comes time to setup the model of Currency as entity, the Type Name Currency is already defined as a Complex Type on the Movie entity.

If you remove one or the other of those config lines, the error should go away - but it won't really resolve your issue, because you need to think about - is Currency in your domain truly an Entity or a ValueObject?

Movie has a Price of type Money which has a property of type Currency - this usage implies it is a ValueObject. But the class has an Id field - the presence of 'identity' implies it is an Entity.

You need to think through the domain modelling and the business processes that are embodied in these types to explore how it should really be treated.

Chris Simon
  • 6,185
  • 1
  • 22
  • 31