2016-04-19 16 views
2

Ich habe eine Entität namens Feld, das wie folgt aussieht:Entity Framework Baumstruktur

Field.cs

class Field 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

So Felder wie eine einfache Liste würde wie folgt aussehen:

1 : First Name 
2 : Last Name 
3 : Gender 
4 : Passport 
5 : Driver License 
6 : Issued 
7 : Expired 

Für jede andere Entität namens Batch möchte ich eine beliebige Struktur von Feldern haben, die wie folgt aussehen könnte:

erster Charge

 First Name |  Last Name  |  Passport   |  Gender 
             | Issued | Expired | 

oder dies:

zweiter Charge

 First Name |  Last Name  |  Gender  |  Driver License | 
                  | Issued | Expired | 

oder anderer Baum von Feldern, in denen Benutzer verschiedene Werte für jedes Feld eingeben würden (einig Felder wären nur Überschriften, wie beispielsweise Passport)

Also meine Felder sind nur eine Liste von Elementen, die wiederverwendet werden können, mit jeder Art von Beziehung zwischen ihnen basierend auf dem Batch. Meine Idee war es, die Batch-Einheit aussehen zu haben:

Batch.cs

class Batch 
{ 
    public int Id { get; set; } 
    public string Fields { get; set; } 
    // other data... 
} 

Wo Felder ist ein JSON-Baum, wie dies für die "erste Charge" aussehen würde:

{ 1, 2, 4: { 6, 7 }, 3 } 

Und wie dies für die zweite Charge:

{ 1, 2, 3, 5: { 6, 7 } } 

Batches könnten sogar mehr tief verschachtelte Felder wie folgt aus:

|    Passport    | 
|  Issued  |  Expired | 
| Month | Year | Month | Year | 

Ist dies der beste Weg, um eine Beziehung, wie dies in der EF zu speichern? Sollte ich das JSON-Feld vermeiden und meine Daten normalisieren? Wenn ja, wie würde ich eine beliebige Baumbeziehung mit EF-Modell zuerst speichern?

+0

Sie sagen nicht, wie Sie planen, die Daten zu speichern, zeigen Sie nur ihre Struktur. Wie würde das Datenmodell aussehen? –

+1

Da dies Modell-zuerst ist, würde EF die Tabelle generieren, und ein Batch-Datensatz würde genau wie beschrieben: Id: 1 - Felder: "{1, 2, 4: {6, 7}, 3}" Ich würde Verwenden Sie dann den JSON aus der Zeichenfolge, um die Felder in einem Stapel anzuzeigen. Vielleicht meinen Sie, wie ich die vom Benutzer eingegebenen Daten speichern würde, und in diesem Fall plante ich, das auf einer Nosql-Datenbank zu speichern, wobei ich grundsätzlich die gleiche JSON-Struktur mit einem Schlüssel/Wert-Paar für jedes Feld verfolgte. –

Antwort

0

Ich schlage vor, dass Sie zwei Klassen Dokument und Staat wie dieser

class Batch 
{ 
public int BatchId { get; set; } 
public string BachFirstName{ get; set; } 
public string BachLastName{ get; set; } 
public string BachGender{ get; set; } 
public Document BachDocument{ get; set; } 
} 

class Document 
{ 
public int DocId { get; set; } 
public string DocDesignation{ get; set; } 
public State DocState{ get; set; } 
} 


class State 
{ 
public int Id { get; set; } 
public string StateDesignation{ get; set; } 
public date StateDate{ get; set; } 
} 
+0

Diese Lösung funktioniert nicht, da es sich bei den Feldern um eine dynamische Liste handelt, die von Benutzern erstellt wird, die sie dann dem Stapel zuordnen und so die in der Frage erwähnte Struktur bilden. –

0

erstellen Wenn Sie es dynamisch wollen, müssen Sie wie folgt Key-Wertetabellen verwenden.

namespace ConsoleApplication1 
{ 
    class Db : DbContext 
    { 
     public DbSet<User> Users { get; set; } 
     public DbSet<Batch> Batches { get; set; } 
    } 

    class User 
    { 
     [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int UserId { get; set; } 
     public virtual List<Batch> Batches { get; set; } 
    } 

    class Batch 
    { 
     [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int BatchId { get; set; } 
     [Required, MaxLength(256)] 
     public string Key { get; set; } 
     [MaxLength(512)] 
     public string Value { get; set; } 
     public virtual List<Batch> Children { get; set; } 
    } 

    class Initializer : DropCreateDatabaseAlways<Db> 
    { 
     protected override void Seed(Db context) 
     { 
      var user = new User(); 
      context.Users.Add(user); 
      user.Batches = new List<Batch>(); 
      user.Batches.AddRange(new List<Batch> 
      { 
       new Batch {Key = "First Name", Value = "John"}, 
       new Batch {Key = "Last Name", Value = "Smith"}, 
       new Batch {Key = "Passport", Children = new List<Batch> 
       { 
        new Batch {Key = "Issued", Value = "2014-02-03"}, 
        new Batch {Key = "Expired", Value = "2015-02-03"}, 
       }} 
      }); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Database.SetInitializer(new Initializer()); 
      using (var db = new Db()) 
      { 
       Console.WriteLine(JsonConvert.SerializeObject(db.Batches.ToList(), Formatting.Indented)); 
       Console.ReadLine(); 
      } 
     } 
    } 
} 

generieren Schema diese Tabelle ist

CREATE TABLE [dbo].[Batches](
    [BatchId] [int] IDENTITY(1,1) NOT NULL, 
    [Key] [nvarchar](256) NOT NULL, 
    [Value] [nvarchar](512) NULL, 
    [Batch_BatchId] [int] NULL, 
    [User_UserId] [int] NULL, 
CONSTRAINT [PK_dbo.Batches] PRIMARY KEY CLUSTERED 
(
    [BatchId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[Batches] WITH CHECK ADD CONSTRAINT [FK_dbo.Batches_dbo.Batches_Batch_BatchId] FOREIGN KEY([Batch_BatchId]) 
REFERENCES [dbo].[Batches] ([BatchId]) 
GO 

ALTER TABLE [dbo].[Batches] CHECK CONSTRAINT [FK_dbo.Batches_dbo.Batches_Batch_BatchId] 
GO 

ALTER TABLE [dbo].[Batches] WITH CHECK ADD CONSTRAINT [FK_dbo.Batches_dbo.Users_User_UserId] FOREIGN KEY([User_UserId]) 
REFERENCES [dbo].[Users] ([UserId]) 
GO 

ALTER TABLE [dbo].[Batches] CHECK CONSTRAINT [FK_dbo.Batches_dbo.Users_User_UserId] 
GO 

Wo [User_UserId] nicht NULL für die Root-Chargen und [Batch_BatchId] ist nicht NULL für die verschachtelt diejenigen. Durch diesen Baum zu gehen, hängt von Ihnen und Ihrer Geschäftslogik ab.