在带有实体框架的ASP.NET MVC中,此上下文仅支持基元类型或枚举类型
本文关键字:类型 上下文 支持 枚举 实体 框架 MVC NET ASP | 更新日期: 2023-09-27 17:58:19
我正在创建一个示例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();
}
问题是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
方法可以推断出Transaction
和Product
之间的关系是多对多的。如果是这种情况,您应该将其指定为EF。根据您当前的模型,这种关系是一对多的。您可以这样更改(在Context
类中):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Transaction>().HasMany(x => x.Products).WithMany();
}
附带说明一下,如果您想将延迟加载添加到模型中,则应该将Transaction
的Products
属性声明为virtual
。