在实体框架代码第一种方法中映射字典

iJa*_*Jay 21 c# dictionary ef-code-first

我有一个这样的字典:

/// <summary>
/// Gets the leave entitlement details.
/// </summary>
/// <value>The leave entitlement details.</value>
public Dictionary<string, EmployeeLeaveEntitlement> LeaveEntitlementDetails { get; set; }  
Run Code Online (Sandbox Code Playgroud)

我想将它映射到数据库.是否可以使用受保护或私有List <>?如:

/// <summary>
/// Gets the leave entitlement details.
/// </summary>
/// <value>The leave entitlement details.</value>
public Dictionary<string, EmployeeLeaveEntitlement> LeaveEntitlementDetails { get; set; } 

public List<EmployeeLeaveEntitlement> LeveEntitlementStore
{
    get
    {
        List<EmployeeLeaveEntitlement> leaveEntitlements = new List<EmployeeLeaveEntitlement>();

        foreach (KeyValuePair<string, EmployeeLeaveEntitlement> leaveType in LeaveEntitlementDetails)
        {
            leaveEntitlements.Add(leaveType.Value);
        }

        return leaveEntitlements;
    }
    set
    {
        foreach (EmployeeLeaveEntitlement item in value)
        {
            this.LeaveEntitlementDetails.Add(item.LeaveType, item);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

谁能帮我?

B12*_*ter 8

EF Core 2.1引入了一项称为值转换的新功能:

值转换器允许在读取或写入数据库时​​转换属性值。

此功能极大地简化了前面答案中提到的序列化方法,这意味着引入了额外的“ helper”属性以及对字典属性的标记[NotMapped]变得不必要。

以下是针对您的情况量身定制的一些代码行(请注意,我正在使用Json.NET,但是可以随意使用您选择的序列化器):

using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace My.Name.Space
{
    public class MyEntity
    {
        public int Id { get; set; }
        public Dictionary<string, EmployeeLeaveEntitlement> LeaveEntitlementDetails { get; set; } 
    }

    public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
    {
        public void Configure(EntityTypeBuilder<MyEntity> builder)
        {
            builder.ToTable("MyEntity");
            builder.HasKey(e => e.Id);

            builder
            .Property(e => e.LeaveEntitlementDetails)
            .IsRequired()
            .HasConversion(
                v => JsonConvert.SerializeObject(v),
                v => v == null
                    ? new Dictionary<string, EmployeeLeaveEntitlement>() // fallback
                    : JsonConvert.DeserializeObject<Dictionary<string, EmployeeLeaveEntitlement>>(v)
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sid*_*Sid 7

在DB中使用XML列

所以今天我遇到了同样的问题,在考虑之后我找到了一个很酷的解决方案,即使我迟到了,也想与社区分享.基本上我已经创建了一个包装系统,将数据保存DictionaryDatabaseas中XML Column,所以稍后我也可以从数据库中查询XML,如果需要的话.

亲这种方法

  • 使用方便
  • 快速实施
  • 你可以使用字典
  • 您可以查询XML列

首先,这是我所有模特的骨头:

public abstract class BaseEntity 
{
    /// <summary>
    /// ID of the model
    /// </summary>
    public int ID { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

假设我有一个包含a Dictionary<string,string>和一个String属性的模型,该属性包含序列化和反序列化字典的逻辑XML,如下面的代码片段所示:

public class MyCoolModel : Base.BaseEntity
{
    /// <summary>
    /// Contains XML data of the attributes
    /// </summary>
    public string AttributesData
    {
        get
        {
            var xElem = new XElement(
                "items",
                Attributes.Select(x => new XElement("item", new XAttribute("key", x.Key), new XAttribute("value", x.Value)))
             );
            return xElem.ToString();
        }
        set
        {
            var xElem = XElement.Parse(value);
            var dict = xElem.Descendants("item")
                                .ToDictionary(
                                    x => (string)x.Attribute("key"), 
                                    x => (string)x.Attribute("value"));
            Attributes = dict;
        }
    }

    //Some other stuff

    /// <summary>
    /// Some cool description
    /// </summary>
    [NotMapped]
    public Dictionary<string, string> Attributes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我实现了一个BaseMapping来自的课程EntityTypeConfiguration<T>

class BaseMapping<TEntity> : EntityTypeConfiguration<TEntity>
    where TEntity : Model.Base.BaseEntity
{
    public BaseMapping()
    {
        //Some basic mapping logic which I want to implement to all my models 
    }
}
Run Code Online (Sandbox Code Playgroud)

和一个自定义后MappingMyCoolModel

class MyCoolModelMapping
    : BaseMapping<Model.MyCoolModel>
{        
    public MyCoolModelMapping() 
    {
        Property(r => r.AttributesData).HasColumnType("xml");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在请注意,当AttributesData它请求值时EntityFramework,只需序列化字典,当我从数据库中检索数据时,同样的情况发生,并且EntityFramework将数据设置为字段,然后反序列化对象并将其设置为字典.

最后我得到overrideOnModelCreating我的DbContext

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new Mappings.BaseMapping<SomeOtherModel>());
        modelBuilder.Configurations.Add(new Mappings.MyCoolModelMapping());
        //Other logic

    }
Run Code Online (Sandbox Code Playgroud)

就是这样!现在我可以使用我的业务逻辑中的字典,这个"包装"处理所有需要将数据保存到DB并从中检索数据的东西.