我有两个类User和Image表:
public class User
{
public Guid? ImageId {get; set;}
public Image Image {get; set;}
}
public class Image
{
public Guid? UserId {get; set;}
public User User {get; set;}
}
用户和图像都可以在没有其他实体的情况下独立存在,但如果它们确实存在关系,则用户只能与一个图像关联,而图像只能有用户,如果它们不为空。我该如何映射?目前我有:
public UserMapping()
{
HasOptional(x => x.ProfileImage).WithOptionalPrincipal(x =>
x.User).Map(x => x.MapKey("UserId"));
}
在ImageMapping上没有任何内容,因为从其他答案中可以看出,它没有将关系映射两次,或者它变得怪异。但是,迁移文件最终会在Image表上生成一个额外的User_Id属性:
CreateTable(
"dbo.Images",
c => new
{
Id = c.Guid(nullable: false),
UserId = c.Guid(),
User_Id = c.Guid(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Users", t => t.User_Id)
.Index(t => t.User_Id);
哪个错了。如何正确地进行映射?
编辑:我也发现了这个问题://stackoverflow.com/questions/21082085/entity-framework-optional-1-to-1-relation-on-both-ends并尝试了原始问题中显示的内容声称工作,但它没有,仍然创建User_Id。答案 0 :(得分:0)
查看this page了解更多详情。
基本上,一对一关系是主体实体的PK在依赖实体中作为PK和FK传递的关系。到目前为止,我可以在这里看到你需要将两个实体映射为彼此之间的可选项,而这在EF中是不可能的,至少不是One to Zero-Or-One。
我知道您希望双方都是可选的,但事实证明EF需要知道您的哪个实体是委托人。所以这是一种改变关系的方法。我建议你在关系中定义你的主体,另一个变成可选的。 E.g:
用户作为校长:
//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处理One to Zero-Or-One关系的方式。
UPDATE!具有唯一约束的两个一对多关系。
让我们尝试一下这种方法。如果这对您有用,请告诉我。
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);
}
}