在带有Entity Framework的ASP.NET MVC中,此上下文仅支持基本类型或枚举类型

时间:2016-07-24 10:49:33

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-5

我正在创建一个示例ASP.NET MVC Web应用程序,我正在遵循数据库的代码优先方法。我想创建products表和transactions表,另外我想通过迁移包含一些示例数据,但是当我尝试Update-Database时,我收到了标题中提到的错误消息。我确切地知道错误发生的原因,那是因为我使用List<Product>,如下所示。但是,我不知道如何解决问题,而交易应包括一个或多个产品。我的代码段可以在下面找到。

public class Product
{
    public int ProductID { get; set; }

    public string Name { get; set; }

}

public class Transaction
{
    public int TransactionID { get; set; }

    public List<Product> Products { get; set; }

}

我还在IdentityModels.cs文件中添加了以下代码行:

public DbSet<Product> Products { get; set; }

public DbSet<Transaction> Transactions { get; set; }

最后,我保存迁移的Configuration.cs文件如下所示:

public Configuration()
{
    AutomaticMigrationsEnabled = true;
    AutomaticMigrationDataLossAllowed = true;
}

protected override void Seed(MyApp.Models.ApplicationDbContext context)
{
    var pr = new List<Product>();
    pr.Add(new Product { Name = "Book" });
    pr.Add(new Product { Name = "Table" });
    pr.Add(new Product { Name = "Chair" });

    pr.ForEach(i => context.Products.AddOrUpdate(p => p.Name, i));
    context.SaveChanges();

    context.Transactions.AddOrUpdate(
        t => t.Products,
        new Transaction { Products = new List<Product>(pr.Where(p => p.Name == "Book" || p.Name == "Table")) },
        new Transaction
        {
            Products = new List<Product>(pr.Where(p => p.Name == "Chair" || p.Name == "Book" || p.Name == "Table"))
        }
    );

    context.SaveChanges();
}

1 个答案:

答案 0 :(得分:1)

问题是AddOrUpdate方法的第一个参数,即identifierExpression。您应该在那里提供原始类型,它确定您何时需要更新以及何时添加。如果数据库中的行与identifierExpression匹配,则会使用您提供的新行进行更新。如果没有,新的将被插入数据库。

您使用t.Products作为标识符,这意味着,当您添加的数据库与其中一个数据库行相同时,Products与您的数据库行之一相同时会发生更新,因为Products没有原始类型。因此,您可以提供基本类型属性或根本不使用此参数(这意味着将插入所有项目)。

context.Transactions.AddOrUpdate(
    //t => t.Products,   //comment this
    new Transaction { 
        Products = new List<Product>(
                        pr.Where(p => p.Name == "Book" || p.Name == "Table")) 
    },
    new Transaction
    {
        Products = new List<Product>(
                pr.Where(p => p.Name == "Chair" || p.Name == "Book" || p.Name == "Table"))
    }
);

<强>建议

通过Seed方法可以推断TransactionProduct之间的关系是多对多。如果是这种情况,您应该为EF指定它。根据您当前的模型,这种关系是一对多的。 您可以像这样更改它(在Context类中):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Transaction>().HasMany(x => x.Products).WithMany();
}

另外,如果您想为模型添加延迟加载,则应将Products的{​​{1}}属性声明为Transaction