实体框架树结构

时间:2016-04-19 20:58:01

标签: c# asp.net json entity-framework tree

我有一个名为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模型首先保存任意树关系?

2 个答案:

答案 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。通过这棵树取决于你和你的业务逻辑。

相关问题