Helper /中间类在数据库(实体框架)中没有列

本文关键字:框架 实体 中间 数据库 Helper | 更新日期: 2023-09-27 18:12:05

首先,我是实体框架的新手,并且正在从我自己编写的数据库框架迁移现有项目,因此我在我选择的解决方案中具有相当大的灵活性。

从我目前的研究来看,一切似乎都是正确的。但是,在构建数据库时,我编写的helper类的表中没有列(除了主键外)。下面是这些类的最简化版本,它们的关系在fluent API中定义。

public class Concept
{
    public long ID { get; set; }
    [Index(IsUnique = true), MaxLength(255)]
    public string Name { get; set; }
}
public class Tag
{
    public long ID { get; set; }
    public virtual Content Subject { get; set; }
    public virtual Concept Concept { get; set; }
}
public class Helper
{
    public long ID { get; set; }
    public virtual Content Subject { get; set; }
    public virtual List<Tag> Instances { get; set; }
    // Helper functionality
}
public class Content
{
    public long ID { get; set; }
    public virtual Helper Helper { get; set; }
    public Content() { Helper = new Helper() { Subject = this }; }
}
<<p> 上下文/strong>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Tag>()
         .HasRequired(t => t.Concept);
     modelBuilder.Entity<Tag>()
         .HasRequired(t => t.Subject);
     modelBuilder.Entity<Helper>()
         .HasRequired(t => t.Subject)
         .WithRequiredDependent(c => c.Helper);
     modelBuilder.Entity<Helper>()
         .HasMany(t => t.Instances);
     modelBuilder.Entity<Content>()
         .HasRequired(c => c.Helper)
         .WithRequiredPrincipal();
    base.OnModelCreating(modelBuilder);
}

Program.cs

static void Main(string[] args)
{
    Content content = null;
    using (var context = new Context())
    {
        content = context.Content.Find(1);
        if (content == null)
        {
            content = new Content();
            context.Content.Add(content);
            context.Helper.Add(content.Helper);
            context.SaveChanges();
        }
    }
}

值得一提的是,当保存数据时,Helper被分配了一个ID,但在第二次加载父类(Content)时,Helper不会像我期望的"virtual"关键字那样惰性加载。我怀疑这是由同样的问题引起的,导致表中没有数据。

我尝试了EF提供的数据注释和流畅的API方法,但似乎有一些基本的东西是我误解的。我希望保留这个helper类,因为它有助于更好地组织代码。

因为我花了相当多的时间研究这些关系/api,并搜索谷歌/SO没有找到任何东西来解决这个问题,特别是任何帮助将非常感激!

<标题>更新:解决方案

感谢评论中的一个问题,我意识到我希望在实体类型本身的表中看到多对多关系的键(即在Helpers表中)。然而,在多对多关系中,键总是放在一个单独的表中(类型名称的连接),该表以前没有创建过。

将'.WithMany();'添加到OnModelCreating函数的Helper部分,如下所示

modelBuilder.Entity<Helper>()
             .HasMany(t => t.Instances)
             .WithMany();

正确地定义了多对多关系,并且按照预期生成了HelperTags表。这是因为多对多关系是单向的(helper总是引用Tags,而Tags从不引用helper)。这也是为什么'WithMany'没有任何参数(因为Tag类中不存在Helper属性)。修复这个简单的疏忽就解决了问题!

Helper /中间类在数据库(实体框架)中没有列

您可能比在on ModelCreate中需要更努力地工作。您可能应该使用标识符重新设计您的类,像这样:

public class Tag
{
    public long Id { get; set; }
    public long SubjectId { get; set; }
    public long ConceptId { get; set; }
    public virtual Content Subject { get; set; }
    public virtual Concept Concept { get; set; }
}

您需要保持ID名称与对象名称完全相同+ ID和EF将神奇地将所有内容链接起来。如果你不希望它们是必需的,那么让id为空(c# 6 == long? SubjectId)。

另外,我已经更改了ID -> ID;我不知道这是否重要。我记得有一次我必须这样做才能使事情正常工作(那是几年前的事了),从那以后我一直这样做。

考虑阅读:

  • 实体框架代码第一公约

关系公约》

除了导航属性,我们建议您包括表示依赖对象的类型上的外键属性。

与主键具有相同数据类型的任何属性属性,并使用遵循以下格式之一的名称表示关系的外键:

  • <navigation property name><principal primary key property name>
  • <principal class name><primary key property name>
  • <principal primary key property name>

如果找到多个匹配项,则按顺序给出优先级上面列出的。

外键检测不区分大小写。

来自MSDN的示例代码:

在下面的示例中,使用导航属性和外键来定义Department和Course类之间的关系。

public class Department 
{ 
    // Primary key 
    public int DepartmentID { get; set; } 
    public string Name { get; set; } 
    // Navigation property 
    public virtual ICollection<Course> Courses { get; set; } 
} 
public class Course 
{ 
    // Primary key 
    public int CourseID { get; set; } 
    public string Title { get; set; } 
    public int Credits { get; set; } 
    // Foreign key 
    public int DepartmentID { get; set; } 
    // Navigation properties 
    public virtual Department Department { get; set; } 
}