4

我正在尝试基于http://www.schema.org上定义的实体使用 Code First 和迁移来构建实体模型和数据库。底线是所有实体都继承自实体“事物”。

迁移会构建数据库,但任何对数据库进行种子设定的尝试都会失败。

一切都继承自 Thing:

    namespace Entities.Models
    {
                public class Thing
                {
                    public Thing()
                    {            
                        Id = Guid.NewGuid();
                        Name = String.Empty;
                    }

                    public Guid           Id               { get; set; }
                    public virtual string Name             { get; set; }

                }

            public class Person : Thing
            {
                public Person()
                    : base()
                {
                    Friends = new List<Person>();
                }

                public string GivenName { get; set; }
                public string FamilyName { get; set; }
                public string Email { get; set; }

                public virtual ICollection<Person> Friends { get; set; }
            }

            public class Event : Thing
            {
                public Event()
                    : base()
                {
                    Attendees = new List<Person>();
                }

                public virtual ICollection<Person> Attendees { get; set; }
                public TimeSpan Duration { get; set; }
                public DateTime? endDate { get; set; }
                public DateTime? StartDate { get; set; }

            }

        public class ThingMap : EntityTypeConfiguration<Thing>
        {
            public ThingMap()
            {
                // Primary Key
                this.Property(t => t.Id)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

                // Properties
                this.Property(t => t.Name)
                    .IsOptional()
                    .HasMaxLength(200);

                // Table & Column Mappings
                this.ToTable("entity_Thing");
          }
       }
    public class PersonMap : EntityTypeConfiguration<Person>
    {
        public PersonMap()
        {
            // Properties
            this.Map<Person>(t =>
            {
                t.MapInheritedProperties();
                t.ToTable("entity_Person");
            });

            // Table & Column Mappings
        }
    }

    public class EventMap : EntityTypeConfiguration<Event>
    {
        public EventMap()
        {
            // Properties
            this.Map<Event>(t =>
            {
                t.MapInheritedProperties();
                t.ToTable("entity_Event");
            });

            // Table & Column Mappings
        }
    }

    public class CitriusSpotsContext : DbContext
    {
        static CitriusSpotsContext()
        {
            Database.SetInitializer<CitriusSpotsContext>(null);
        }

        public CitriusSpotsContext()
            : base("Name=CitriusSpotsContext")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new ThingMap());
            modelBuilder.Configurations.Add(new PersonMap());
            modelBuilder.Configurations.Add(new EventMap());
        }

        public DbSet<Thing> Things { get; set; }
        public DbSet<Person> People { get; set; }
        public DbSet<Event> Events { get; set; }
    }

}
4

2 回答 2

3

我目前正在使用类似的模型,我知道这个答案很晚,但它可能会有所帮助。

首先,TPH、TPT 和 TPC 是在我们的数据库中建模继承的机制。如果我们不需要为多态查询、更新或保存建模继承,我们不需要遵循 TP* 约定。

让我重申一下。TPH、TPT 和 TPC 是可选的数据库继承建模策略。如果我们的应用程序不需要多态查询、更新或插入,我们不需要遵循 TP* 约定。

我的基本项目设置与您的非常相似。在我的项目中,我有一个抽象类,项目中的每个类都继承自该类。它被命名XModelBase,我相信它对应于您的Thing课程。

我使用这个抽象类来实现一些将我的 biz 规则验证连接到实体框架的验证机制的基本方法。该类还确保为每个实体捕获审计值,并且该类包含其他通用属性 (KeyId),并为通用流程提供原型/模板。

我们的模型之间唯一真正的区别是,当您使用数据类型作为主键时,myXModelBase将 aint作为主键的数据类型(所有类随后都会继承)Guid

如果我是正确的,您和我将永远不需要执行如下查询:

场景一:

var query = from t in context.Things select t;

这种类型的查询在我们的场景中没有意义。为什么我们要选择数据库中的每个对象?我们不会也不会

我们也永远不会通过我们的抽象类保存对象,例如:

场景二:

var person = new Person() {Email = "something@somewhere.com"};
context.Things.Add(person);

相反,我们只是这样做:

场景 3:

var person = new Person() {Email = "something@somewhere.com"};
context.People.Add(person);

由于我们不需要容纳Scenario 1or Scenario 2,因此我们不需要Things成为单独的基表 (TPT)。我们也不需要或不想以 TPC 的不可见多态方式访问或保存我们的子类表;因此,当您考虑它时,我们真的永远不需要以下属性:

public DbSet<Thing> Things { get; set; }

当我们想要/需要对多态关联建模时,我们只需要在我们的对象上下文中使用这个 DbSet 属性。

从我们的上下文中删除该属性并摆脱我们对基类的模型配置是继承自由的第一步。

接下来,我们将从MapInheritedProperties()子类模型配置中删除 ,因为继承的属性将自动映射。我们只是留下我们.ToTable的子类对象的名称。

同样,我有一个intXModelBase类主键,所以我可以简单地用如下[Key]属性标记它:

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

但是因为我没有DbSet为我的XModelBase类创建表或使用,所以所有继承的子类都将具有独立的自动递增主键,这些主键[Key]在我的 XModelBase类中配置了这个属性。

如果我正确理解了您的问题,这些信息应该会为您指明正确的方向,但如果我没有解决您的问题,我很想知道您最终是如何解决这些问题的。

希望这可以帮助!

于 2013-03-14T20:00:21.250 回答
-2

似乎您正在使用代码优先的方法,并且您正在尝试将架构生成为 c# 类。

要使用代码优先,您的基类必须从 DbContext 继承,然后您可以为数据库通信构建适当的方法。

在您的情况下,Thing 应该从 DbContext 继承,因为它将是您的存储库,然后您可以开始创建您的实体。

实体是简单的对象类,因此您可以从任何其他类继承它们。一个示例结构可能是这样的:

class Thing : DbContext
{
    public DbSet<Product> Products { get; set; }
}

class Product
{
    public int Id { get; set; }
    public int ProductName { get; set; }
}

如需更多信息,请访问 http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspxhttp://www。 codeproject.com/Articles/318010/Entity-Framework-Code-First-Let-s-Try-It

希望这会有所帮助。

于 2012-12-24T19:27:37.597 回答