在entity framework代码第一种方法中映射字典

我有这样的字典:

///  /// Gets the leave entitlement details. ///  /// The leave entitlement details. public Dictionary LeaveEntitlementDetails { get; set; } 

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

 ///  /// Gets the leave entitlement details. ///  /// The leave entitlement details. public Dictionary LeaveEntitlementDetails { get; set; } public List LeveEntitlementStore { get { List leaveEntitlements = new List(); foreach (KeyValuePair leaveType in LeaveEntitlementDetails) { leaveEntitlements.Add(leaveType.Value); } return leaveEntitlements; } set { foreach (EmployeeLeaveEntitlement item in value) { this.LeaveEntitlementDetails.Add(item.LeaveType, item); } } } 

谁能帮我?

entity framework目前不支持本地映射字典。

有关更多信息和解决方法,请参阅以下内容:

entity framework4 POCO与字典

EF Code First – 将字典或自定义类型映射为nvarchar

http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/a51ba903-2b8b-448e-8677-d140a0b43e89/

在DB中使用XML列

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

亲这种方法

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

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

 public abstract class BaseEntity { ///  /// ID of the model ///  public int ID { get; set; } } 

假设我有一个包含Dictionary和一个String属性,该属性包含在XML序列化和反序列化字典的逻辑,如下面的代码片段:

 public class MyCoolModel : Base.BaseEntity { ///  /// Contains XML data of the attributes ///  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 ///  /// Some cool description ///  [NotMapped] public Dictionary Attributes { get; set; } } 

然后我实现了一个BaseMapping类,它来自EntityTypeConfiguration

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

并在MyCoolModel的自定义Mapping MyCoolModel

 class MyCoolModelMapping : BaseMapping { public MyCoolModelMapping() { Property(r => r.AttributesData).HasColumnType("xml"); } } 

现在请注意,当EntityFramework请求AttributesData值时,它只是序列化字典,当我从数据库中检索数据并且EntityFramework将数据设置到字段时会发生相同的情况,然后对该字段进行反序列化并将其设置为dict。

最后我override了我的DbContext的OnModelCreating

  protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Configurations.Add(new Mappings.BaseMapping()); modelBuilder.Configurations.Add(new Mappings.MyCoolModelMapping()); //Other logic } 

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

我有一个与EF类似的问题,我想将一个查询返回列表转换为类属性的字典等价物。 非常类似于你想如何让LeaveEntitlementDetails包装LeveEntitlementStore例如:

 class A { [NotMapped()] public Dictionary Data {get; set} //refers to Data.Values public ICollection DataAsList {get; set} } 

我希望DataAsList基本上包装Data.Values

经过大量的反复试验,我发现EF,对于集合(可能更多),通过getter的返回值(而不是setter)进行更改。 即从我的db初始化时:

 var pollquery=From bb In DBM.Dbi.DataTable.Includes("DataAsList") Where bb.Id = id Select bb; ClassA objInstance = pollquery.First(); 

从来没有调用过ClassA.DataAsList的setter,但是在我的对象的内部构造过程中getter ….结论:EF使用从属性ClassA.DataAsList的getter中检索的引用,并向其添加对象。

所以我在ObservableCollection中包含了我的getter的DataAsList返回值,并为CollectionChanged args添加了一个处理程序,果然,我的CollectionChanged处理程序正在拾取.Add调用。

所以inheritance我的hackaround -aroundaround:

 class A : INotifyPropertyChanged { //So we can let EF know a complex property has changed public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged; //here's our actual data, rather than an auto property, we use an explicit member definition so we can call PropertyChanged when Data is changed private Dictionary m_data = new Dictionary(); //not mapped property as it's not mapped to a column in EF DB [NotMapped()] public Dictionary Data { get { return m_data; } set { m_data = value; //now call PropertyChanged for our Front (so EF will know it's been changed) if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("DataAsList")); } } } //this is our front for the data, that we use in EF to map data to [DebuggerHidden()] public ICollection DataAsList { get { ObservableCollection ob = new ObservableCollection(Data.Values()); ob.CollectionChanged += Handles_entryListChanged; return ob; } set { //clear any existing data, as EF is trying to set the collections value Data.Clear(); //this is how, in my circumstance, i converted my object into the dictionary from an internal obj.Id property' foreach (DataType entry in value) { entryions.Add(entry.id, entry); } } } //This will now catch wind of any changes EF tries to make to our DataAsList property public void Handles_entryListChanged(object sender, NotifyCollectionChangedEventArgs e) { //Debugger.Break() switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (DataType entry in e.NewItems) { m_data.Add(entry.Id, entry); } break; default: Debugger.Break(); break; } } } 

注意魔术是:

 public ICollection DataAsList { get { ObservableCollection ob = new ObservableCollection(Data.Values()); ob.CollectionChanged += Handles_entryListChanged; return ob; } 

我们订阅对返回列表所做的任何更改,以及我们处理的Handles_entryListChanged ,并基本上复制所做的任何更改。