在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
,并基本上复制所做的任何更改。