我目前正在开发一个网站项目,它将一个Repository作为一个单独的项目,用c#编写,使用我以前从未使用过的Entity Framework。我遇到了一个问题,如果我在运行时遇到数据库错误,尝试通过前端添加新容器。
我花了一天时间研究为什么这不起作用,最后决定我必须问这个问题。我已经看了很多已经问过的问题,但没有一个帮助过我。
我正在使用Entity Framework,由于外键约束,目前无法在数据库中添加“Vessel”。
代码
VesselRepository.cs
public int CreateVessel(Vessel newVessel)
{
using (BoatContext dbContext = new BoatContext())
{
dbContext.Vessels.Add(newVessel);
dbContext.SaveChanges();
//return new vessel id
return Convert.ToInt32(newVessel.VesselId);
}
}
这是发生错误的方法,特别是在SaveChanges()
行上,并带有以下消息:
"The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Vessel_Attachment1". The conflict occurred in database "BoatRegistration", table "dbo.Attachment", column 'VesselId'.
The statement has been terminated."
这些是VesselConfiguration.cs
& AttachmentConfiguration.cs
个文件:
public class VesselConfiguration :EntityTypeConfiguration<Vessel>
{
public VesselConfiguration()
: base()
{
HasKey(v => v.VesselId);
ToTable("Vessel");
}
}
class AttachmentConfiguration : EntityTypeConfiguration<Attachment>
{
public AttachmentConfiguration()
: base()
{
HasKey(a => a.VesselId);
HasRequired(attment => attment.Vessel).WithOptional(vsl => vsl.Attachment);
ToTable("Attachment");
}
}
在数据库级别,这是我用于Attachment
和Vessel
表的结构:
最后这是 BoatContext 类:
public class BoatContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Vessel> Vessels { get; set; }
public DbSet<Club> Clubs { get; set; }
public DbSet<Attachment> Attachments { get; set; }
public BoatContext()
: base("Name=BoatRegistrationConnectionString")
{
System.Data.Entity.Database.SetInitializer<BoatContext>(null);
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new PersonConfiguration());
modelBuilder.Configurations.Add(new VesselConfiguration());
modelBuilder.Configurations.Add(new ClubConfiguration());
modelBuilder.Configurations.Add(new AttachmentConfiguration());
base.OnModelCreating(modelBuilder);
}
}
我理解错误消息告诉我,当附件表中不存在外键时,我正在尝试将记录插入到Vessel表中,但是Vessel表中的vesselId
具有{ {1}},所以当我调试并检查Identity Specification
时,它总是在插入之前设置为零。
我尝试过的事情
尝试在vesselId
之前添加dbContext.Attachments.Add(newVessel.Attachment);
但收到同样的错误,我尝试将SaveChanges()
添加到HasOptional(vsl => vsl.Attachment).WithRequired(attment => attment.Vessel);
,但这没有任何区别,我也是尝试将VesselConfiguration.cs
设置为vesselId
,但收到错误,因为null
不能为空。
我还运行了SQL事件探查器,并且从前端获取的一些测试数据导致上述错误失败的查询是:
vesselId
当我在保存之前检查exec sp_executesql N'INSERT [dbo].[Vessel]([PersonId], [VesselName], [ClassType],
[Makemodel], [Length], [Construction], [HullColour], [EngineTypeHP], [DataTagNumber],
[MMSINumber], [ArchiveStatus], [PermitNumber], [RegistrationNumber])
VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, NULL, NULL)
SELECT [VesselId]
FROM [dbo].[Vessel]
WHERE @@ROWCOUNT > 0 AND [VesselId] = scope_identity()',N'
@0 int,@1 nvarchar(max) ,@2 nvarchar(max) ,@3 nvarchar(max) ,
@4 nvarchar(max) ,@5 nvarchar(max) ,@6 nvarchar(max) ,@7 nvarchar(max) ,
@8 nvarchar(max) ,@9 nvarchar(max) ,@10 bit',
@0=27,@1=N'dgfgdf',@2=N'dfgdf',@3=N'dgfgdf',@4=N'34534',@5=N'dfgdfg',
@6=N'dgfgf',@7=N'43534543',@8=N'5433',@9=N'33445',@10=0
对象时,所有内容都按顺序查看,我输入的船只数据全部存在,附件详细信息全部存在,即使newVessel
匹配已存在记录在Person表中,唯一关闭的是PersonId
,但我认为这将由插件上的SQL Server处理。就好像它没有对内存中的VesselId
信息做任何事情,但Attachment
类是Attachment
的属性:
Vessel
答案 0 :(得分:0)
使用Entity Framework的方式与我使用它的方式有很大不同。 我无法确定问题是由你的方式引起的,但你是对的。实体框架应该在执行SQL时为您创建一个ID。
无论如何,如果没有别的办法,你可以试试这个。
public int CreateVessel(Vessel newVessel)
{
using (BoatContext dbContext = new BoatContext())
{
newVessel.VesselId = new Vessel().VesselId;
//newVessel.Attachment = null
// OR
//Attachment attach = new Attachment();
//newVessel.Attachement = attach;
dbContext.Vessels.Add(newVessel);
dbContext.SaveChanges();
//return new vessel id
return Convert.ToInt32(newVessel.VesselId);
}
}
答案 1 :(得分:0)
我认为这里的问题在于您的数据库架构。
列VesselId在表'Attachments'中被配置为主键,但它也应该用作外键,它引用表Vessel的'VesselId'列。
另一方面,表'Vessel'中的'VesselId'列应重命名为'Id'并仅用作主键,绝对不能用作外键。
在您的情况下,无法添加新的Vessel实体,因为表'Vessel'中的外键约束会检查表'Attachment'中是否存在包含VesselId的条目,但情况并非如此。
希望这有帮助。