查看此页面了解更多详情。
基本上一对一的关系是主实体的 PK 在从属实体中作为 PK 和 FK 传递的关系。据我在这里看到的,您需要将两个实体映射为彼此之间的可选实体,这在 EF 中实际上是不可能的,至少不是一到零或一。
我了解您希望双方都是可选的,但事实证明 EF 需要知道您的哪个实体是主体。所以这是一种改变关系的方法。我建议你在关系中定义你的主要实体,另一个成为可选的。例如:
用户作为主体:
//Your entities
public class Image
{
public Guid UserId { get; set; }
public virtual User User { get; set; }
}
public class User
{
public Guid UserId { get; set; }
public virtual Image Image { get; set; }
}
//Mappings:
public class ImageMappingConfiguration : EntityTypeConfiguration<Image>
{
public ImageMappingConfiguration()
{
HasKey(x => x.UserId);
}
}
public class UserMappingConfiguration : EntityTypeConfiguration<User>
{
public UserMappingConfiguration()
{
HasKey(x => x.UserId);
HasOptional(x => x.Image)
.WithRequired(x => x.User);
}
}
在添加迁移后你会得到这个:
public override void Up()
{
CreateTable(
"dbo.Images",
c => new
{
UserId = c.Guid(nullable: false)
})
.PrimaryKey(t => t.UserId)
.ForeignKey("dbo.Users", t => t.UserId)
.Index(t => t.UserId);
CreateTable(
"dbo.Users",
c => new
{
UserId = c.Guid(nullable: false)
})
.PrimaryKey(t => t.UserId);
}
看到用户作为 PK 和 FK 传递给 Image 的主键吗?这就是 EF 处理一对零或一关系的方式。
更新!两个具有唯一约束的一对多关系。
让我们尝试一下这种方法。让我知道这是否适合您。
public sealed class Image
{
public Image()
{
Users = new List<User>();
}
public Guid Id { get; set; }
public Guid? UserId { get; set; }
public List<User> Users { get; set; }
public User User { get; set; }
}
public sealed class User
{
public User()
{
Images = new List<Image>();
}
public Guid Id { get; set; }
public Guid? ImageId { get; set; }
public List<Image> Images { get; set; }
public Image Image { get; set; }
}
//Mappings:
public class ImageMappingConfiguration : EntityTypeConfiguration<Image>
{
public ImageMappingConfiguration()
{
HasKey(x => x.Id);
Property(x => x.UserId)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute("IX_ImageMustBeUnique")
{
IsUnique = true
}));
HasMany(x => x.Users)
.WithOptional(x => x.Image)
.HasForeignKey(x => x.ImageId)
.WillCascadeOnDelete(true);
}
}
public class UserMappingConfiguration : EntityTypeConfiguration<User>
{
public UserMappingConfiguration()
{
HasKey(x => x.Id);
Property(x => x.ImageId)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute("IX_UserMustBeUnique")
{
IsUnique = true
}));
HasMany(x => x.Images)
.WithOptional(x => x.User)
.HasForeignKey(x => x.UserId);
}
}
用法:
//test adding a user and an image.
var user = new User
{
Id = Guid.NewGuid(),
};
var image = new Image
{
Id = Guid.NewGuid(),
};
using (var ctx = new Context())
{
ctx.Users.Add(user);
ctx.Images.Add(image);
ctx.SaveChanges();
//associate them
user.Images.Add(image);
image.Users.Add(user);
ctx.SaveChanges();
//try to add a second image to the user
var image2 = new Image
{
Id = Guid.NewGuid()
};
try
{
user.Images.Add(image2);
ctx.SaveChanges();
}
catch (DbUpdateException ex)
{
Console.WriteLine(ex);
}
}