Entity Framework - Inheritance - Zero to one Relat

2019-08-17 03:54发布

问题:

I have a Inheritance Hierarchy where Action is parent of ActionCompleted and ActionCancelled. Order class has a zero to one ActionCompleted and ActionCancelled. I have tried TPH and TPT (even tried edmx) but unable to get Entity to understand this relationship between Order and child actions, please suggest how do I map?

//Classes
    public class Order
    {
        public   int OrderId { get; set; }
        public string Name { get; set; }
        public   ActionCompleted ACO { get; set; }
        public ActionCancelled ACA { get; set; }

    }

public class Action
{
    public   int ActionID { get; set; }
    public   DateTime ActionDT { get; set; }
    public   Order Order { get; set; }
}

public class ActionCompleted : Action
{

}
public class ActionCancelled : Action
{
    public int CancelledByPhysician { get; set; }
}

//Mappings

public class EDISContext:DbContext
{
    public EDISContext()
        : base("EDISContext")
    { }


    public DbSet<Order> Orders { get; set; }

    public DbSet<Action> Actions { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>().ToTable("Orders");

        modelBuilder.Entity<Action>().HasKey(a => a.ActionID);

        modelBuilder.Entity<Action>().Map(m => m.ToTable("Actions"))
                                              .Map<ActionCompleted>(m => m.ToTable("ActionCompleted"))
                                              .Map<ActionCancelled>(m => m.ToTable("ActionCancelled"));

        //modelBuilder.Entity<Action>().HasRequired(a => a.Order).WithOptional().Map(m => m.MapKey("DiagOrderId"));
        modelBuilder.Entity<ActionCompleted>().HasRequired(a => a.Order).WithOptional().Map(m => m.MapKey("DiagOrderId"));
        modelBuilder.Entity<ActionCancelled>().HasRequired(a => a.Order).WithOptional().Map(m => m.MapKey("DiagOrderId"));

    }

}

Code used to save data:

EDISContext db = new EDISContext();
var ord1 = db.Orders.FirstOrDefault(o => o.OrderId == 1);
ActionCompleted ac= new ActionCompleted();
ac.ActionDT = DateTime.Now;
ac.Order = ord1;
db.Actions.Add(ac);
db.SaveChanges();

Script of DB tables:

CREATE TABLE [dbo].[Orders](
    [OrderId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NULL,
) ON [PRIMARY]

CREATE TABLE [dbo].[Actions](
    [ActionID] [int] IDENTITY(1,1) NOT NULL,
    [ActionDT] [datetime] NOT NULL,
    [DiagOrderID] [int] NULL,
) ON [PRIMARY]

CREATE TABLE [dbo].[ActionCompleted](
    [ACID] [int] IDENTITY(1,1) NOT NULL,
    [ActionID] [int] NOT NULL,
) ON [PRIMARY]

CREATE TABLE [dbo].[ActionCancelled](
    [ACAID] [int] IDENTITY(1,1) NOT NULL,
    [ActionID] [int] NOT NULL,
    [CancelledByPhysician] [int] NULL,
 ) ON [PRIMARY]

回答1:

When using code first, it's always useful to at least try letting EF create the database for you - this is the default behavior (will look for local instance of SQL Server called .\SQLEXPRESS). If you create the database manually and want to control the column names, which is what seems like is happening, you'll need to specify the column name with the fluent API. See http://msdn.microsoft.com/en-us/library/hh295845(v=vs.103).aspx and http://msdn.microsoft.com/en-us/library/hh295847(v=VS.103).aspx for some examples that should cover what you're getting stuck on.

Just for reference, the database you've created would have the following tables and column names:

CREATE TABLE [dbo].[ActionCancelled](
    [ActionID] [int] NOT NULL,
    [CancelledByPhysician] [int] NOT NULL,
PRIMARY KEY CLUSTERED ( [ActionID] ASC )
)

CREATE TABLE [dbo].[ActionCompleted](
    [ActionID] [int] NOT NULL,
PRIMARY KEY CLUSTERED ( [ActionID] ASC )
)

CREATE TABLE [dbo].[Actions](
    [ActionID] [int] IDENTITY(1,1) NOT NULL,
    [ActionDT] [datetime] NOT NULL,
    [Order_OrderId] [int] NULL,
PRIMARY KEY CLUSTERED ( [ActionID] ASC )
)

CREATE TABLE [dbo].[Orders](
    [OrderId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [ACO_ActionID] [int] NULL,
    [ACA_ActionID] [int] NULL,
PRIMARY KEY CLUSTERED ( [OrderId] ASC )
)


回答2:

If you insist on creating and maintaining the database yourself, I advise you to try using the Database First workflow, not Code First. Create an Entity Data Model from your database then generate the POCOs. It will make your life much easier, especially in the case you change your database schema.

As for the EDM to understand table relationships, you must set them in the database. I don't know if you alread did it since you haven't pasted any script that creates the foreign keys but VS should not have any problems understanding propperly defined schemas.