[英]Entity Framework tree structure
我有一個名為Field的實體,它看起來像:
Field.cs
class Field
{
public int Id { get; set; }
public string Name { get; set; }
}
因此字段看起來像一個簡單的列表,如下所示:
1 : First Name
2 : Last Name
3 : Gender
4 : Passport
5 : Driver License
6 : Issued
7 : Expired
對於每個稱為Batch的實體,我想要一個任意的字段樹,可能看起來像這樣:
第一批
First Name | Last Name | Passport | Gender
| Issued | Expired |
或這個:
第二批
First Name | Last Name | Gender | Driver License |
| Issued | Expired |
或其他任何字段樹,其中用戶將為每個字段鍵入不同的值(例如,某些字段只是標題,例如Passport)
因此,我的字段只是可以重用的元素列表,基於批處理在它們之間具有任何類型的關系。 我的想法是使批處理實體如下所示:
Batch.cs
class Batch
{
public int Id { get; set; }
public string Fields { get; set; }
// other data...
}
其中fields是“ First Batch”的JSON樹,如下所示:
{ 1, 2, 4: { 6, 7 }, 3 }
第二批是這樣的:
{ 1, 2, 3, 5: { 6, 7 } }
批次甚至可以具有如下更深層的嵌套字段:
| Passport |
| Issued | Expired |
| Month | Year | Month | Year |
這是在EF中存儲這樣的關系的最佳方法嗎? 我應該避免使用JSON字段並對數據進行規范化嗎? 如果是這樣,我將如何使用EF模型優先保存任意樹關系?
我建議您創建兩個類文檔,並像這樣聲明
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; }
}
如果要使其動態,則需要使用像這樣的鍵值表。
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();
}
}
}
}
該表的生成Schema
為
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
其中[User_UserId]
不是NULL
根批次和[Batch_BatchId]
不是NULL
為嵌套的。 遍歷這棵樹取決於您和您的業務邏輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.