我有一个名为Field的实体,它看起来像:
Field.cs
truncate table foo restart identity
所以字段看起来就像这样一个简单的列表:
class Field
{
public int Id { get; set; }
public string Name { get; set; }
}
对于另一个名为Batch的实体,我希望有一个任意的字段树,可能如下所示:
第一批
1 : First Name
2 : Last Name
3 : Gender
4 : Passport
5 : Driver License
6 : Issued
7 : Expired
或者这个:
第二批
First Name | Last Name | Passport | Gender
| Issued | Expired |
或任何其他字段树,用户可以为每个字段键入不同的值(某些字段只是标题,例如Passport)
所以我的字段只是一个可以重用的元素列表,它们之间有任何基于批处理的关系。我的想法是让批处理实体看起来像:
Batch.cs
First Name | Last Name | Gender | Driver License |
| Issued | Expired |
其中字段是JSON树,对于“第一批”看起来像这样:
class Batch
{
public int Id { get; set; }
public string Fields { get; set; }
// other data...
}
第二批就像这样:
{ 1, 2, 4: { 6, 7 }, 3 }
批次甚至可以拥有更深层次的嵌套字段:
{ 1, 2, 3, 5: { 6, 7 } }
这是在EF中存储此类关系的最佳方式吗?我应该避免使用JSON字段并规范化我的数据吗?如果是这样,我将如何使用EF模型首先保存任意树关系?
答案 0 :(得分:0)
我建议你创建两个类文档并像这样说明
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; }
}
答案 1 :(得分:0)
如果你想要它是动态的,你需要使用像这样的键值表。
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
。通过这棵树取决于你和你的业务逻辑。