我使用实体框架 6 和代码优先方法,并且我希望将两个实体放入同一个表中。我做错了什么?
[Table("Review")]
public class Review
{
public int Id { get; set; }
public PictureInfo PictureInfo { get; set; }
public int PictureInfoId { get; set; }
}
[Table("Review")]
public class PictureInfo
{
[Key, ForeignKey("Review")]
public int ReviewId { get; set; }
public Review Review { get; set; }
}
我得到的错误: 实体类型“PictureInfo”和“Review”无法共享表“Review”,因为它们不在同一类型层次结构中,或者它们之间没有匹配主键的有效一对一外键关系。
我做错了什么?
问题似乎在于该关系被解释为一对 0..1 而不是一对一。
Review 端的外键
int PictureInfoId
不需要/被忽略,因此它的非空性并没有使关系的 Review 端成为必需的。删除这个不需要的键并将 [Required] 属性添加到 PictureInfo 导航属性解决了这个问题。
这是更正后的复习课程。
[Table("Review")]
public class Review
{
public int Id { get; set; }
[Required]
public PictureInfo PictureInfo { get; set; }
}
我已经成功地用 Fluent api 实现了你想要的。 Fluent api 提供了比数据注释更丰富的配置选项。我对你的实体类做了一些更改:
public class Review
{
public int Id { get; set; }
public PictureInfo PictureInfo { get; set; }
}
PictureInfoId 属性不是必需的,因为外键关系将在两个实体的主键上完成。
public class PictureInfo
{
public int Id { get; set; }
public Review Review { get; set; }
}
因为 Review 和 PictureInfo 将映射到同一个表,所以它们需要共享相同的主键列,因此对于 PictureInfo 和 Review,该列应该具有相同的名称。如果您想在 PictureInfo 中保留名为 ReviewId 的主键属性,您可以执行此操作,但您需要将其名称映射到“Id”。最后是 DbContext:
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Review>().HasKey( e => e.Id );
modelBuilder.Entity<Review>()
.HasRequired(e => e.PictureInfo)
.WithRequiredDependent(e => e.Review);
modelBuilder.Entity<Review>().Map(m => m.ToTable("Review"));
modelBuilder.Entity<PictureInfo>().Map(m => m.ToTable("Review"));
modelBuilder.Entity<PictureInfo>().HasKey(e => e.Id);
base.OnModelCreating(modelBuilder);
}
public DbSet<Review> Reviews { get; set; }
public DbSet<PictureInfo> PictureInfos { get; set; }
}
OnModelCreating 拥有流畅的 API 映射定义。您所要做的就是在两个同名实体上定义主键,将这两个实体以 1-1 关系绑定,然后将它们映射到同一个表。
解决此问题的另一种方法是创建仅包含所需字段的视图。然后将实体映射到视图。
(这些测试和错误是针对 EF 6.1.3 编写的)
[Table("Review")]
public class Review
{
[Key]
public int Id { get; set; }
public PictureInfo PictureInfo { get; set; }
}
[Table("Review")]
public class PictureInfo
{
[Key]
public int Id { get; set; }
public Review Review { get; set; }
}
使用上述实体,我收到此错误:
无法确定之间关联的主要端 类型。该关联的主要目的必须明确 使用关系流畅 API 或数据进行配置 注释。
[Table("Review")]
public class Review
{
[Key]
public int Id { get; set; }
[Required]
public PictureInfo PictureInfo { get; set; }
}
[Table("Review")]
public class PictureInfo
{
[Key]
public int Id { get; set; }
[Required]
public Review Review { get; set; }
}
实体类型“Review”和“PictureInfo”不能共享表格 “审查”,因为它们不在同一类型层次结构中或不属于同一类型层次结构 与匹配的主键具有有效的一对一外键关系 它们之间的钥匙。
[Table("Review")]
public class Review
{
[Key]
public int Id { get; set; }
[Required, ForeignKey("Id")]
public PictureInfo PictureInfo { get; set; }
}
[Table("Review")]
public class PictureInfo
{
[Key]
public int Id { get; set; }
[Required, ForeignKey("Id")]
public Review Review { get; set; }
}
无法确定之间关联的主要端 类型。该关联的主要目的必须明确 使用关系流畅 API 或数据进行配置 注释。
[Table("Review")]
public class Review
{
[Key, ForeignKey("PictureInfo")]
public int Id { get; set; }
public PictureInfo PictureInfo { get; set; }
}
[Table("Review")]
public class PictureInfo
{
[Key, ForeignKey("Review")]
public int Id { get; set; }
public Review Review { get; set; }
}
using System.Linq;
using System.Data.Entity;
namespace Sample
{
class Program
{
static void Main(string[] args)
{
using (var context = new EmployeeDBContext())
{
var result = context.Set<Employee>().Include(x => x.Department).ToArray();
}
}
}
public class EmployeeDBContext : DbContext
{
public EmployeeDBContext() : base("EmployeeDB") { }
public DbSet<Employee> Employee { get; set; }
public DbSet<Department> Department { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().ToTable("Departments").HasKey(x => x.DepartmentId);
modelBuilder.Entity<Employee>().ToTable("Employees").HasKey(x => x.Id);
//ForeignKey mapping
modelBuilder.Entity<Employee>().HasRequired(x => x.Department).WithMany().HasForeignKey(x => x.DepartmentId);
base.OnModelCreating(modelBuilder);
}
}
//Domain Entity
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Department Department { get; set; }
public int DepartmentId { get; set; }
}
//Domain Entity
public class Department
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
}
}
我想在这里为遇到此错误的人添加注释,但并不意味着让两个实体都指向同一个表...
确保您没有意外地在“表”属性中放置了错误的表名称。
该错误是由于Table“PictureInfo”指令中的表定义重复而引起的。您只需要编辑该指令即可。
[表(“评论”)] 公开课回顾 { ... }
[表(“评论”)] 公共课图片信息 { ... }
对于
[表(“评论”)] 公开课回顾 { ... }
[表格(“图片信息”)] 公共课图片信息 { ... }