一个Document
可以包含多个Images
;一个Image
只能引用一个Document
:
CREATE TABLE [Images]
(
[Id] [bigint] NOT NULL IDENTITY(1,1),
...
[DocumentId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Images_Id]
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Images_Documents]
FOREIGN KEY([DocumentId]) REFERENCES [Documents]([Id])
)
CREATE TABLE [Documents]
(
[Id] [uniqueidentifier] NOT NULL DEFAULT NEWID(),
...
[DocumentId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Documents_Id]
PRIMARY KEY CLUSTERED ([Id] ASC),
...
)
c#类:
public class Image
{
public long Id {get; set;}
public string Name {get; set;}
...
public Document Document { get; set; }
}
public class Document
{
public Guid Id {get; set;}
public string Name {get; set;}
....
public ICollection<Image>? Images { get; set; } = new List<Image>();
}
最后是映射
public class ImageConfiguration : IEntityTypeConfiguration<Image>
{
public void Configure(EntityTypeBuilder<Image> builder)
{
builder.HasKey(it => it.Id);
....
builder.HasOne(it => it.Document).WithMany(c => c.Images);
}
}
当我尝试插入Document
和Image
时:
var document = new Document
{
Name = "Test doc",
Images = new List<Image>{new Image{ Name = "test"}};
};
var db = new MyDbContext();
db.Documents.Add(document);
db.SaveChanges();
我得到这个错误:
Microsoft.EntityFrameworkCore。DbUpdateException:保存实体更改时发生错误。
详情请参阅内部异常。Microsoft.Data.SqlClient。sql异常:INSERT语句与外键约束冲突"FK_Images_Documents".
冲突发生在数据库"mydb"、表"文档"、列"Id"中。
如果我为图像更改创建表脚本,并使属性DocumentId
为NULL,并删除相应的FK (FK_Images_Documents
),并将Document
标记为Image
模型上的可空值,则插入(文档和图像)将成功通过。
我做错了什么?
您的配置一团糟。您可能已经定义了一个额外的外键属性。所以删除你的流畅配置,重新开始。
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
namespace EfCore6Test
{
public class Image
{
public long Id { get; set; }
public string Name { get; set; }
public Document Document { get; set; }
}
public class Document
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<Image>? Images { get; set; } = new List<Image>();
}
public class Db : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Document>();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=localhost;database=efCore6Test;Integrated Security=true;TrustServerCertificate=true", o => o.UseRelationalNulls(true))
.LogTo(Console.WriteLine, LogLevel.Information);
base.OnConfiguring(optionsBuilder);
}
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var document = new Document()
{
Name = "Test doc",
Images = new List<Image> { new Image { Name = "test" } }
};
db.Set<Document>().Add(document);
db.SaveChanges();
}
}
}
}
关于"注意力测试"的好问题:)
当我尝试执行这个示例时,得到以下错误:
SqlException: Cannot insert the value NULL into column 'DocumentId', table 'testDb.dbo.Documents'; column does not allow nulls. INSERT fails.
原因是当你创建db-table Documents时:
CREATE TABLE [Documents]
(
[Id] [uniqueidentifier] NOT NULL DEFAULT NEWID(),
...
[DocumentId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Documents_Id]
PRIMARY KEY CLUSTERED ([Id] ASC),
...
)
我想你偶尔会添加过多的列" documententid& quot;到db-table Documents not null(但您已经在那里定义了Id主键列),这不会得到set
var document = new Document
{
Name = "Test doc",
Images = new List<Image>{new Image{ Name = "test"}};
};
所以我们有一个Documents db-table的不可空列documententid没有被设置,所以错误发生的预期行为
为避免以上错误,请删除多余的"文档编号";列