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)
谁能帮我?
Eri*_* J. 20
实体框架目前不支持本地映射字典.
有关更多信息和解决方法,请参阅以下内容:
EF Code First - 将字典或自定义类型映射为nvarchar
http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/a51ba903-2b8b-448e-8677-d140a0b43e89/
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)
所以今天我遇到了同样的问题,在考虑之后我找到了一个很酷的解决方案,即使我迟到了,也想与社区分享.基本上我已经创建了一个包装系统,将数据保存Dictionary到Databaseas中XML Column,所以稍后我也可以从数据库中查询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)
和一个自定义后Mapping的MyCoolModel
class MyCoolModelMapping
: BaseMapping<Model.MyCoolModel>
{
public MyCoolModelMapping()
{
Property(r => r.AttributesData).HasColumnType("xml");
}
}
Run Code Online (Sandbox Code Playgroud)
现在请注意,当AttributesData它请求值时EntityFramework,只需序列化字典,当我从数据库中检索数据时,同样的情况发生,并且EntityFramework将数据设置为字段,然后反序列化对象并将其设置为字典.
最后我得到override了OnModelCreating我的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并从中检索数据的东西.