2017-08-22 10 views
0

私は2015年多重継承(多分抽象クラス?)C#Entity Frameworkの

が、私は」のVisual Studioを使ってC#でのEntity Frameworkの6(コード・ファースト)に基づいて、データベースの開発に取り組んできた最後の週現在、継承が提供するすべてのオプションを扱っています。 この時点でデータベースの標準に従って、私は主キーで複数の継承を実装する必要があります。 これはどういう意味ですか? これは、別のクラスから継承するクラスを実装し、そのクラスを親クラスと区別するための独自のPKを実装する必要があることを意味します。この時点で、私はTPCでそれを実装することができ、親クラスを抽象化し、親にPKを定義しません。これは、この時点でコードのサンプルです

public abstract class Person 
    { 

     public string Name { get; set; } 
     public string LastName { get; set; } 

    } 

    [Table("Students")] 
    public class Student : Person 
    { 

     [Key]public int Id_student { get; set; } 
     public string code_s { get; set; } 
     public virtual ICollection<Course> courses { get; set; } 

    } 

は、その後、私は自分のデータベースを構築するために従うべき基準が別の継承親として学生を取り、別の作成を実装するために私を必要とする(これは動作し、私はそれをテストしています)学生から継承するクラス。私が持っていた 最初と愚かなアイデアが

ChildOfChild : Student 

を書いて、それは同じくらい簡単にすることでした。しかし、明らかにそれは動作しませんでした。

それでは、私は学生クラス抽象クラスを作成する可能性がありますが、私がクラス抽象クラスを宣言したとき、それをインスタンス化してテーブルを作成することはできませんでした。私は抽象クラスやこれを開発するのに役立つ可能性のある他の方法を使用して、これを行うための他の方法があるかどうかはわかりません。 私がこれを解決しようとしている問題を理解していない場合は、私が持っているコードのサンプルです。

public abstract class Person 
    { 

     public string Name { get; set; } 
     public string LastName { get; set; } 

    } 

    [Table("Students")] 
    public class Student : Person 
    { 

     [Key]public int Id_student { get; set; } 
     public string code_s { get; set; } 
     public virtual ICollection<Course> courses { get; set; } 

    } 

    [Table("ExchangeStudent")] 
    public class ExchangeStudent : Student 
    { 

     [Key]public int Id_exchange { get; set; } 
     public string HomeUniversity {get; set;} 

    } 
+0

「学生」と「ExchangeStudents」を別々のテーブルに分割したいのですが、すべての生徒を選択して生徒をクラスにリンクするときに、自分が難しくなると思います。あなたが直面している問題の例ですか?_ – Scrobi

+0

これは私が実装しなければならない事例の一例です。実際のケースはStudent-ExchangeStudentよりもはるかに複雑です。 実モデルには、他のクラスが継承する一般クラスと、この子エンティティを継承する他のエンティティがあります。 –

+0

PKとしてのPersonIdだけではないのはなぜですか?それは普通のやり方です。 –

答えて

0

私の理解では、自分のプライマリキーと外部キーの両方が1対1の関係を定義する2つのテーブルが必要です。 C#コードでは、これらのテーブルに継承関係を持たせます。

Entity Frameworkでこれを行うことがわかる唯一の方法は、要件を分割することです。まず、必要なテーブル構造を表すデータベースモデルを作成します。

namespace DAO 
{ 
    public abstract class Person 
    { 
     public string Name { get; set; } 
    } 

    public class Student 
    { 
     public int StudentId { get; set; } 
     public string Nickname { get; set; } 
    } 

    //Use navigation property rather than inheritance to define the relationship 
    public class ExchangeStudent 
    { 
     public int ExchangeStudentId { get; set; } 
     public string HomeUniversity { get; set; } 
     public virtual Student Student { get; set; } 
    } 
} 

これは私に次のコードを与えた:あなたは別の名前空間に定義するための新しいオブジェクトを作成することができます学生とExchangeStudent間の継承関係を持っている必要があれば今すぐ

public override void Up() 
     { 
      CreateTable(
       "dbo.ExchangeStudent", 
       c => new 
        { 
         ExchangeStudentId = c.Int(nullable: false, identity: true), 
         HomeUniversity = c.String(), 
         Student_StudentId = c.Int(), 
        }) 
       .PrimaryKey(t => t.ExchangeStudentId) 
       .ForeignKey("dbo.Student", t => t.Student_StudentId) 
       .Index(t => t.Student_StudentId); 

      CreateTable(
       "dbo.Student", 
       c => new 
        { 
         StudentId = c.Int(nullable: false, identity: true), 
         Nickname = c.String(), 
         Name = c.String(), 
        }) 
       .PrimaryKey(t => t.StudentId); 

     } 

namespace BusinessObject 
{ 
    public abstract class Person 
    { 
     public string Name { get; set; } 
    } 

    public class Student 
    { 
     public int StudentId { get; set; } 
     public string Nickname { get; set; } 
    } 

    //ExchangeStudent derives from Student 
    public class ExchangeStudent : Student 
    { 
     public int ExchangeStudentId { get; set; } 
     public string HomeUniversity { get; set; } 
    } 
} 

次に、2つのオブジェクトをマッピングするクラスを作成するだけです。あなたのためにこれを行うことができるサードパーティライブラリもあります。

+1

こんにちはScrobi、まず、すべての助けと献身に感謝します。また、学生もPersonから継承していると考えていますか? 私は異なる名前空間の使用に慣れていませんが、あなたのソリューションをよりよく理解するために、この側面を調査します。あなたのソリューションは非常によく見え、最初のコヒーレントなソリューションです。助けをもう一度ありがとう:) –

0

2つの主キーを持つことはできません。 StudentId_studentを主キーとして定義し、ExchangeStudentにはId_exchangeを主キーとして定義します。 Personにプロパティ 'Id'を実装し、Id_studentId_exchangeのプロパティを取り除きます。

+0

私が持っていたモデルではありません。私が欲しかったモデルは、独自のPKを持つクラスと、このクラスを継承する別のクラスです。また、この子クラスのためのものであり、親クラスに関連しないPKを持ち、次にこれを継承する他のクラス親クラスに関連しない独自のPKを持つことができます。 これはかなり複雑ですが、私はいくつかの "専門家"に私の問題のための解決策があることを願っています –

+0

私はあなたが継承の概念を誤解していると思います。すべての継承クラスには独自の主キーがあります。各継承クラスでプライマリキーを定義する場合は、親からプライマリキープロパティをオーバーライドする必要があります。新しいキーワードを追加します。 – Hintham

+0

しかし、同じ親クラスから継承した異なるクラスのすべての主キーは、それらの間で関連しません。 Id_teacher = 10、Id_teacherとId_studentを持つ教師(このクラスもPersonから継承します)が存在することになります(つまり、私が言ったように)親クラスのPkです子でオーバーライドされ、これらのPKはテーブルの生徒と教師のseparetlyに保存されます。これはあなたが意味することですか? –

0
public abstract class Student : Person 
    { 
     [Key]public int Id_student { get; set; }   
    } 

    public class LocalStudent : Student{ 

    } 

    public class ExchangeStudent : Student 
    {   
     public string HomeUniversity {get; set;} 
    } 

しかし、私は

public class Student : Person 
    { 

     [Key]public int Id_student { get; set; } 
     public string code_s { get; set; } 
     public virtual ICollection<Course> courses { get; set; } 
     public ExchangeInfo ExchangeInfo{get;set;} 
    } 


    public class ExchangeInfo : Student 
    { 

     [Key]public int Id_exchange { get; set; } 
     public Student Student{get;set;} 
     public string HomeUniversity {get; set;}  
    } 

できHomeUniversityは、学生の属性のように聞こえるような何かを考えるでしょうか? 2つのテーブルから2つのテーブルを選択するのではなく、1つのテーブルで2つのテーブルを操作するのがより快適になります。 2人の学生とExchangeStudentへのコースのようにテーブルのリンクを作成する方法も教えてください。

+0

これは、私が複雑なモデルでやろうとしていることのほんの単純な例です。実際のエンティティはPerson-Student-ExchangeStudentではなく、実際に実装しようとしているこの例の概念を説明したかっただけです。 私が実装しようとしているのは、独自のPKを持つクラスと、このクラスを継承する別のクラスと、この子クラスのみのPKを持ち、この親の親クラスまたは他の子エンティティに関連しないクラスを継承するクラスこの子からも親クラスに関連しない独自のPKを持つことができます。 –

+0

だから、PKを使ってアイテムを継承して再定義しようとするのは珍しいので、最初の例では共通のプロパティを持つ2つの別個のエンティティを分割しようとしています。あなたは本当の例を提供できますか?おそらくすべてのプロパティはありませんが、実際のビジネスでは少なくとも現実世界の例 – zxxc

0

Idを持たないPersonはありますか?そうでない場合は、PersonIdプロパティを付けます。流暢なAPIで、TPCをモデル化する場所を定義します。このIDは、生徒と交換学生のプライマリキーです。

public class Person 
{ 
    public int Id {get; set; 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

public class Student : Person 
{ 
    // the primary key is in the base class 
    public string code_s { get; set; } 
    public virtual ICollection<Course> courses { get; set; } 
} 

public class ExchangeStudent : Student 
{ 
    // the primary key is in one of the base classes 
    public string HomeUniversity {get; set;} 
} 

あなたのDbContextはHasKeyが必要な場合、私はわからないthis link

class MyDbContext : DbContext 
{ 
    public DbSet<Student> Students {get; set;} 
    public DbSet<ExchangeStudent> ExchangeStudents {get; set;} 

    protected override OnModelCreating(...) 
    { // configure Student and ExcahngeStudent as TPC, 
     // if needed define primary key 
     modelBuilder.Entity<Student>() 
     .HasKey(student => student.Id) 
     .Map(m => 
     { 
      m.MapInheritedProperties(); 
      m.ToTable("Students"); 
     }); 

     modelBuilder.Entity<ExchangeStudent>() 
     .HasKey(student => student.Id) 
     .Map(m => 
     { 
      m.MapInheritedProperties(); 
      m.ToTable("ExchangeStudents"); 
     }); 
    } 

のようにTPCを設定します。主キーはnaming conventionsに従うので、必要ではない可能性があります。

属性の上に流暢なAPIを使用する利点は、異なるDbContextを指定するだけで、異なるデータベースモデルで同じクラスとクエリを自由に使用できるという点です。

+0

こんにちはHarald、これは私が探していたものではない、私が望んでいたのは、基本クラスはPKを持っていない、自分自身のPKとし、2番目の子は、この2番目の子のテーブル内の各行を識別するための別のPKを持つ必要があります。このようなものを実装することは可能でしょうか? –

+0

なぜ2つの主キーが必要ですか?最初の子の主キーの価値はどういう意味ですか?主キーが親クラスにあるのはなぜですか?あなたはすべてのクラスが正確に1つのプライマリキーを持っていることを確信します。 –

+0

完璧な方法は::各クラスに1つのプライマリキーがあり、各プライマリキーは親PKから独立しています。これで、親がId = 10を取得した場合、Id = 10の子が存在する可能性があり、Id = 10を持つ可能性のある子が欲しいと思っても問題はありません。 –