如何将EF5导航属性定义为多种类型

时间:2013-02-16 16:12:08

标签: entity-framework entity-framework-5

我有一个我想在数据库中表示的共享类型。我需要先知道代码是否可行,或者设计是否糟糕。 (请指出你的推理来源)。

这是布局:

public class A
{
    public Guid Id;
    public Guid ParentId; // Points to either B or C
    public string Foo;
}

public class B
{
    public Guid Id;
    public virtual ICollection<A> ManyA { get; set; }
    // Other fields
}

public class C
{
    public Guid Id;
    public virtual ICollection<A> ManyA { get; set; }
    // Other fields
}

我使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]注释管理了GUID PK,我相信这会使这成为可能。

目标是保持A - 表简单;我希望不要有B_IdC_Id列,因为我认为它们是不必要的,并且将来可能会有D类型有很多{ {1}} 就像AB一样。此外,此方案还用于其他一些关系。

我认为问题的精神是显而易见的,但EF特定的班级成员只是为了说明。如果他们需要改变,那就这样吧。

(我为这个人为的例子感到抱歉,但是,揭露其真实性质,IMO并没有澄清问题)。

另外,我试着搜索几个小时!我不知道找到合适答案的正确命名法。我对数据库和EF一般都很陌生。

2 个答案:

答案 0 :(得分:0)

不要使用Guid制作索引,为什么选择硬道路? :S

使用DataAnnotations,例如:

一堂课:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.Mvc;

namespace app.Models
{
    [Table("A")]
    public class A
    {

        [Key]
        public int AId { get; set; }

        [Required(ErrorMessage = "Campo obrigatório")]
        [DisplayName("Title")]
        [StringLength(100)]
        public string Title { get; set; }
        public virtual ICollection<B> bCollection { get; set; } 
    }
}

B班:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.Mvc;

namespace app.Models
{
    [Table("B")]
    public class B
    {
        [ScaffoldColumn(false)]
        [Key]
        public int BId { get; set; }

        [DisplayName("Description")]
        [StringLength(100)]
        public string Description { get; set; }

        public virtual ICollection<A> AList{ get; set; } 
    }
}

您可以在此处查看更多详细信息:link !!! 有关EF5数据注释的更多详细信息:link

答案 1 :(得分:0)

我发现我可以为BC类型创建一个公共基类型。例如:

class Program
{
    static void Main(string[] args)
    {
        using (var context = new Ctx())
        {
            var b = new B();
            var c = new C();
            b.ManyA.Add(new A());
            c.ManyA.Add(new A());

            context.Cs.Add(c);
            context.Bs.Add(b);

            context.SaveChanges();
        }
    }
}

public class Ctx : DbContext
{
    public DbSet<A> As { get; set; }
    public DbSet<B> Bs { get; set; }
    public DbSet<C> Cs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BaseClass>()
            .HasMany<A>(b => b.ManyA)
            .WithRequired(a => a.BaseObject)
            .WillCascadeOnDelete(true);
    }
}

public class BaseClass
{
    public BaseClass() { ManyA = new HashSet<A>(); }

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public virtual ICollection<A> ManyA { get; set; }
}

public class A
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public BaseClass BaseObject { get; set; }
    public string Foo { get; set; }
}

public class B : BaseClass
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public string SomeProperty { get; set; }
}

public class C : BaseClass
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public int SomeOtherProperty { get; set; }
}

并且,基于this Msdn article,将导致Table Per Hierarchy数据库布局。 TPH比TPT表现更好,我认为这可能是一个答案。

我真的希望有更简单的东西,但是性能是底线,毕竟