实体框架-Fluent API-创建奇怪列PK:FK FK

时间:2018-07-05 07:18:42

标签: c# entity-framework-6 ef-model-builder

我的项目是数据库优先,并且我正在使用Entity Framework 6.2.0。

所以我有以下简单的例子:

Person [1]    [n] Link_Table [n]    [1] Area
======            ==========            ====
ID                ID                    ID 
                  PersonID (FK)         
                  AreaID (FK)

现在,当使用以下代码时,它会通过内部异常“无效的列名'Area2_ID'”。

Db_Context db = new Db_Context();

// getting all links with specific "personID"
List<Link_Table> links = db.Link_Table.Where(item => item.PersonID == personID).ToList();

// now getting all areas
List<Area> areas= new List<Area>();
foreach (Link_Table link in links)
{
    // ERROR
    areas.Add(db.Area.Where(item => item.ID == link.areaID).First());
}

我已经阅读了其他用户关于此问题的一些文章,该问题应该在(自动生成的) OnModelCreating 中。

modelBuilder.Entity<Area>()
            .Property(e => e.Description)
            .IsUnicode(false);

        modelBuilder.Entity<Area>()
            .HasOptional(e => e.Area1)
            .WithRequired(e => e.Area2);

无论出于何种原因在代码中使用EF并创建一个新的Area-Object,它不仅会显示“ ID”-属性,还会显示“ Area1”-和“ Area2”-属性。

问题 我该如何处理?列“ Area1_ID”和“ Area2_ID”仅存在于EF中,不存在于数据库中。我可以删除这些属性或其他方法来防止出现异常吗?

编辑: 我的模特:

[Table("Area")]
public partial class Area
{
    public Guid ID { get; set; }

    [StringLength(40)]
    public string Name { get; set; }

    [Column(TypeName = "text")]
    public string Description{ get; set; }

    public virtual Area Area1 { get; set; }

    public virtual Area Area2 { get; set; }
}

public partial class Link_Table
{
    public Guid ID { get; set; }

    public Guid? Person_ID { get; set; }

    public Guid? Area_ID { get; set; }

    public virtual Person Person{ get; set; }
}

[Table("Person")]
public partial class Person
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Person()
    {
        Link_Table = new HashSet<Link_Table>();
    }

    public Guid ID { get; set; }
}

3 个答案:

答案 0 :(得分:0)

这行看起来很可疑:

areas.Add(db.Area.Where(item => item.ID == link.areaID).First());

item.ID是链接表记录的索引,而不是区域记录。

areas.Add(db.Area.Where(item => item.AreaID == link.areaID).First());

答案 1 :(得分:0)

对我来说,您的目标不是很清楚,但是您可以按照以下方式重构代码:

此代码:

// now getting all areas
List<Area> areas= new List<Area>();
foreach (Link_Table link in links)
{
    // ERROR
    areas.Add(db.Area.Where(item => item.ID == link.areaID).First());
}

可以替换为:

var areas=links.Select(link => link.Area).ToList() // if you decide to add a navigation property

var areas=db.Areas.Where(area => links?.Any(link=>link.areaID==area.Id)).ToList();

您可能从.First()得到的错误很可能是将来用于.FirstOrDefault()

请参见下面的代码优先实现示例:

class Program
{
    static void Main(string[] args)
    {
        var db = new ApplicationDbContext();
        var person = new Person();
        IQueryable<Link> personLinks = db.Links.Where(x => x.PersonId == person.Id);
        List<Area> personAreas = personLinks.GroupBy(x => x.Area).Select(x => x.Key).ToList(); 
    }
}

public class Person
{
    public int Id { get; set; }
    public ICollection<Link> Links { get; set; }
}

public class Link
{
    public int Id { get; set; }
    public int PersonId { get; set; }
    public Person Person { get; set; }
    public int AreaId { get; set; }
    public Area Area { get; set; }
}

public class Area
{
    public int Id { get; set; }
    public ICollection<Link> Links { get; set; }
}

public class ApplicationDbContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
    public DbSet<Area> Areas { get; set; }
    public DbSet<Link> Links { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Link>()
            .HasRequired(x => x.Person)
            .WithMany(x => x.Links)
            .HasForeignKey(x => x.PersonId)
            .WillCascadeOnDelete(true);

        modelBuilder.Entity<Link>()
            .HasRequired(x => x.Area)
            .WithMany(x => x.Links)
            .HasForeignKey(x => x.AreaId)
            .WillCascadeOnDelete(false);

        base.OnModelCreating(modelBuilder);
    }
}

在这里您可以首先了解有关实体框架代码的更多信息follow this link

答案 2 :(得分:0)

您上次运行数据库迁移的时间是什么时候?如果您的模型是正确的,并且您的数据库说缺少字段,那么该数据库与代码不匹配。