【发布时间】:2019-06-02 02:05:42
【问题描述】:
我是 Entity Framework Core 的新手,在为 mssql 数据库做种时遇到了麻烦。我有一个主题模型和一个具有一对多关系的分配模型(主题有一个 ICollection)。
我尝试添加:
storeContext.Entry<Subject>(subject1).State = EntityState.Detached;
为数据库创建的所有对象,但它仍然给出相同的错误。
尝试运行 asp.net 核心应用程序时出现此错误:
Exception thrown: 'System.InvalidOperationException' in Microsoft.EntityFrameworkCore.dll
An exception of type 'System.InvalidOperationException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code
The instance of entity type 'Assignment' cannot be tracked because another instance with the same key value for {'AssignmentId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
DatabaseInitializer 类:
using FoxAcademicManager.Backend.Models;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FoxAcademicManager.Backend.Data
{
public class DatabaseInitializer
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AcademicManagerContext>();
//do your stuff....
context.Database.EnsureCreated();
if (context.Subjects.Any()) return;
if (context.Events.Any()) return;
var subject1 = new Subject
{
SubjectId = 1,
Title = "Physics",
Description = "The AB Physics course",
GradeEarned = null,
GradeOverall = null,
};
var subject2 = new Subject
{
SubjectId = 2,
Title = "Chemistry",
Description = "A AB Chem course",
GradeEarned = null,
GradeOverall = null,
};
var assignment1 = new Assignment
{
Date = new DateTime(2020, 3, 1, 9, 0, 0),
Name = "Assignment 1",
Description = "Forces and Newton's Laws of Motion",
Score = 80,
Weight = 0.2,
AssignmentId = 1,
SubjectId = 1
};
var assignment2 = new Assignment
{
Date = new DateTime(2020, 3, 1, 9, 0, 0),
Name = "Assignment 2",
Description = "Gravity",
Score = 90,
Weight = 0.2,
AssignmentId = 2,
SubjectId = 1
};
var assignment3 = new Assignment
{
Date = new DateTime(2020, 3, 1, 9, 0, 0),
Name = "Assignment 3",
Description = "Frequency",
Score = 70,
Weight = 0.2,
AssignmentId = 3,
SubjectId = 1
};
var exam1 = new Assignment
{
Date = new DateTime(2020, 5, 1, 10, 0, 0),
Name = "Exam 1",
Description = "The first exam",
Score = 85,
Weight = 0.6,
AssignmentId = 1,
SubjectId = 2
};
var exam2 = new Assignment
{
Date = new DateTime(2020, 6, 1, 11, 0, 0),
Name = "Exam 2",
Description = "The second exam",
Score = 75,
Weight = 0.6,
AssignmentId = 2,
SubjectId = 2
};
var assignmentz1 = new Assignment
{
Date = new DateTime(2020, 5, 11, 12, 0, 0),
Name = "Assignment 1",
Description = "The first Chem grade",
Score = 85,
Weight = 0.2,
AssignmentId = 3,
SubjectId = 2
};
context.Subjects.AddRange(new Subject[] { subject1, subject2 });
subject1.Assignments = new List<Assignment> { assignment1, assignment2, assignment3 };
subject2.Assignments = new List<Assignment> { exam1, exam2, assignmentz1 };
context.UpdateRange(subject1, subject2);
context.SaveChanges();
}
}
}
}
这是 Startup.cs 文件:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
using FoxAcademicManager.Backend.Data;
using Microsoft.EntityFrameworkCore;
namespace FoxAcademicManager.Backend
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<AcademicManagerContext>
(options => options.UseSqlServer(connection));
services.AddSwaggerGen(options =>
options.SwaggerDoc("v1", new Info { Title = "Academic Manager", Version = "v1"})
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSwagger();
if(env.IsDevelopment() || env.IsStaging())
{
app.UseSwaggerUI(options =>
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Academic Manager v1")
);
}
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
DatabaseInitializer.Initialize(app.ApplicationServices);
}
}
}
【问题讨论】:
-
AssignmentId不是Assignment的PK(主键)吗?如果是(看起来),它应该是唯一的。并且您的种子数据包含重复的AssignmentIds - 例如,assignment1和exam1有AssignmentId == 1。您可能应该让数据库生成这些 ID。Subject也一样。您基本上需要使用填充的Assignments集合创建Subject对象(不要指定硬编码的 PK 和 FK),然后只需执行context.Subjects.AddRange(…)- EF Core 将负责其余的工作。
标签: c# asp.net-core entity-framework-core ef-core-2.2