entity framework实体不在DataSpace.OSpace(_workspace.GetItemCollection(DataSpace.OSpace))中,而是在DataSpace.CSpace中
我一直在使用XML
for entity Framework。 我试图创建一种可以在运行时注入属性的实体,首先我创建了动态的DynamicEntity
对象
public class DynamicEntity : DynamicObject { Dictionary dynamicMembers = new Dictionary(); public override bool TrySetMember(SetMemberBinder binder, object value) { dynamicMembers[binder.Name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (dynamicMembers.TryGetValue(binder.Name, out result)) { return dynamicMembers.TryGetValue(binder.Name, out result); } result = ""; return true; } }
然后实体inheritance自此
public partial class QUOTE_HOUSE : DynamicEntity
(当我从db获取数据后手动设置属性时,它似乎确实有效)。
所以基于这种删除属性的机制,我试图做另一个将属性插入到XML中的东西,并且整个事情似乎保持不错(至少它不会破坏映射,它通常在XML不正确时执行var mappingCollection = new StorageMappingItemCollection(conceptualCollection, storageCollection, new[] {mappingXml.CreateReader()});
)。
执行查询时出现问题是EF
实体类型QUOTE_HOUSE不是当前上下文的模型的一部分。
描述:执行当前Web请求期间发生未处理的exception。 请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
exception详细信息:System.InvalidOperationException:实体类型QUOTE_HOUSE不是当前上下文的模型的一部分。
[InvalidOperationException:实体类型QUOTE_HOUSE不是当前上下文模型的一部分。]
System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType(Type entityType)+208
System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)+50
在为EF
加载pdb后,我在System.Data.Entity.Internal.InternalContext
跟踪了TryUpdateEntitySetMappingsForType
基本上我的QUOTE_HOUSE
不在this._workspace.GetItemCollection(DataSpace.OSpace)
, UpdateEntitySetMappings
尝试从中映射它。
它检查它是否在this._entitySetMappingsCache.ContainsKey(entityType))
并且因为它不是它然后尝试更新映射迭代this._workspace.GetItemCollection(DataSpace.OSpace)
我的项目不存在
但是我可以看到我的实体确实存在于this._workspace.GetItems(DataSpace.CSpace)
。
完整的UpdateEntitySetMappings
如下所示:
private void UpdateEntitySetMappings() { ObjectItemCollection objectItemCollection = (ObjectItemCollection) this._workspace.GetItemCollection(DataSpace.OSpace); ReadOnlyCollection items = this._workspace.GetItems(DataSpace.OSpace); Stack entityTypeStack = new Stack(); foreach (EntityType entityType1 in items) { entityTypeStack.Clear(); EntityType cspaceType = (EntityType) this._workspace.GetEdmSpaceType((StructuralType) entityType1); do { entityTypeStack.Push(cspaceType); cspaceType = (EntityType) cspaceType.BaseType; } while (cspaceType != null); EntitySet entitySet = (EntitySet) null; while (entitySet == null && entityTypeStack.Count > 0) { cspaceType = entityTypeStack.Pop(); foreach (EntityContainer entityContainer in this._workspace.GetItems(DataSpace.CSpace)) { List list = entityContainer.BaseEntitySets.Where((Func) (s => s.ElementType == cspaceType)).ToList(); int count = list.Count; if (count > 1 || count == 1 && entitySet != null) throw Error.DbContext_MESTNotSupported(); if (count == 1) entitySet = (EntitySet) list[0]; } } if (entitySet != null) { EntityType entityType2 = (EntityType) this._workspace.GetObjectSpaceType((StructuralType) cspaceType); Type clrType1 = objectItemCollection.GetClrType((StructuralType) entityType1); Type clrType2 = objectItemCollection.GetClrType((StructuralType) entityType2); this._entitySetMappingsCache[clrType1] = new EntitySetTypePair(entitySet, clrType2); } } }
实体如何进入this._workspace.GetItemCollection(DataSpace.OSpace)? 为什么实体会在CSpace
而不在OSpace
?
编辑:对于那些可能想要获得赏金的人,下面是您可能需要设置环境来重现问题的组件。
public class SystemToDatabaseMapping { public SystemToDatabaseMapping(string system, string databaseType, string database, string connectionString, Type enitityType) { System = system; Database = database; DatabaseType = databaseType; ConnectionString = connectionString; EntityType = enitityType; } public Type EntityType { get; set; } public string System { get; set; } public string Database { get; set; } public string DatabaseType { get; set; } public string ConnectionString { get; set; } public List ColumnsToModify { get; set; } } public abstract class ColumnToModify { protected ColumnToModify(string table, string column) { Table = table; Column = column; } public string Table { get; set; } public string Column { get; set; } public abstract bool IsRemove{ get; } } public class ColumnToRemove : ColumnToModify { public ColumnToRemove(string table, string column) : base(table, column) { } public override bool IsRemove { get { return true; } } } public class ColumnToAdd : ColumnToModify { public ColumnToAdd(string table, string column, Type type) : base(table, column) { this.Type = type; } public override bool IsRemove { get { return false; } } public Type Type { get; set; } }
首先从db生成的实体,( DynamicEntity
代码在上面)
public partial class QUOTE_HOUSE : DynamicEntity { public long UNIQUE_ID { get; set; } }
数据库的DbContext需要构造函数重载
public partial class EcomEntities : DbContext { public EcomEntities(DbConnection connectionString) : base(connectionString, false) { } public virtual DbSet QUOTE_HOUSE { get; set; } .... }
进行色谱柱注射的机制(它是一个粗略的原型,所以对它的外观有多么容易),当注入try string column我知道它映射好了。
public static class EntityConnectionExtensions { public static IEnumerable ElementsAnyNS(this IEnumerable source, string localName) where T : XContainer { return source.Elements().Where(e => e.Name.LocalName == localName); } public static IEnumerable ElementsAnyNS(this XContainer source, string localName) { return source.Elements().Where(e => e.Name.LocalName == localName); } private static void ModifyNodes(XElement element, List tableAndColumn) { if (element.Attribute("Name") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("Name").Value) || element.Attribute("StoreEntitySet") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("StoreEntitySet").Value)) { var matchingRemoveSelectParts = tableAndColumn.Where(oo => oo.IsRemove && element.Value.Contains(string.Format(""{0}"."{1}" AS "{1}"", oo.Table, oo.Column))).ToList(); if (matchingRemoveSelectParts.Any()) { foreach (var matchingRemoveSelectPart in matchingRemoveSelectParts) { var definingQuery = element.ElementsAnyNS("DefiningQuery").Single(); definingQuery.Value = definingQuery.Value.Replace(string.Format(", n"{0}"."{1}" AS "{1}"", matchingRemoveSelectPart.Table, matchingRemoveSelectPart.Column), ""); } } else { var nodesToRemove = element.Nodes() .Where(o => o is XElement && ((XElement) o).Attribute("Name") != null && tableAndColumn.Any(oo => oo.IsRemove && ((XElement) o).Attribute("Name").Value == oo.Column)); foreach (var node in nodesToRemove.ToList()) { node.Remove(); } if (element.Attribute("Name") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("Name").Value)) { var elementsToAdd = tableAndColumn.Where(o => !o.IsRemove && o.Table == element.Attribute("Name").Value); if (new[] {"Type="number"", "Type="varchar2"", "Type="date""}.Any(o => element.ToString().Contains(o))) { foreach (var columnToModify in elementsToAdd) { var columnToAdd = (ColumnToAdd) columnToModify; var type = new[] {typeof (decimal), typeof (float), typeof (int), typeof (bool)}.Contains(columnToAdd.Type) ? "number" : columnToAdd.Type == typeof (DateTime) ? "date" : "varchar2"; var precision = ""; var scale = ""; var maxLength = ""; if (type == "number") { precision = "38"; scale = new[] {typeof (decimal), typeof (float)}.Contains(columnToAdd.Type) ? "2" : "0"; } if (type == "varchar2") { maxLength = "500"; } var newProperty = new XElement(element.GetDefaultNamespace() + "Property", new XAttribute("Name", columnToAdd.Column), new XAttribute("Type", type)); if (!string.IsNullOrWhiteSpace(precision)) { newProperty.Add(new XAttribute("Precision", precision)); } if (!string.IsNullOrWhiteSpace(scale)) { newProperty.Add(new XAttribute("Scale", scale)); } if (!string.IsNullOrWhiteSpace(maxLength)) { newProperty.Add(new XAttribute("MaxLength", maxLength)); } element.Add(newProperty); } } else if ( new[] {"Type="Decimal"", "Type="String"", "Type="DateTime"", "Type="Boolean"", "Type="Byte"", "Type="Int16"", "Type="Int32"", "Type="Int64""}.Any( o => element.ToString().Contains(o))) { foreach (var columnToModify in elementsToAdd) { var columnToAdd = (ColumnToAdd) columnToModify; var type = new[] {typeof (decimal), typeof (float), typeof (int), typeof (bool)}.Contains(columnToAdd.Type) ? "Decimal" : columnToAdd.Type == typeof (DateTime) ? "DateTime" : "String"; var precision = ""; var scale = ""; var maxLength = ""; if (type == "Decimal") { precision = "38"; scale = new[] {typeof (decimal), typeof (float)}.Contains(columnToAdd.Type) ? "2" : "0"; } if (type == "String") { maxLength = "500"; } var newProperty = new XElement(element.GetDefaultNamespace() + "Property", new XAttribute("Name", columnToAdd.Column), new XAttribute("Type", type)); if (!string.IsNullOrWhiteSpace(precision)) { newProperty.Add(new XAttribute("Precision", precision)); } if (!string.IsNullOrWhiteSpace(scale)) { newProperty.Add(new XAttribute("Scale", scale)); } if (!string.IsNullOrWhiteSpace(maxLength)) { newProperty.Add(new XAttribute("MaxLength", maxLength)); newProperty.Add(new XAttribute("FixedLength", "false")); newProperty.Add(new XAttribute("Unicode", "false")); } element.Add(newProperty); } } } } if (element.Attribute("Name") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("Name").Value) && element.GetNamespaceOfPrefix("store") != null && element.Attribute(element.GetNamespaceOfPrefix("store") + "Type") != null && element.Attribute(element.GetNamespaceOfPrefix("store") + "Type").Value == "Tables") { var matchingAddSelectParts = tableAndColumn.Where(o => !o.IsRemove && o.Table == element.Attribute("Name").Value); foreach (var matchingAddSelectPart in matchingAddSelectParts) { var definingQuery = element.ElementsAnyNS("DefiningQuery").Single(); var schemaRegex = new Regex(string.Format("\nFROM \"([a-zA-Z0-9]*)\".\"{0}\"", matchingAddSelectPart.Table)); var schema = schemaRegex.Matches(definingQuery.Value)[0].Groups[1].Value; definingQuery.Value = definingQuery.Value.Replace( string.Format("nFROM "{0}"."{1}" "{1}"", schema, matchingAddSelectPart.Table), string.Format(", n"{0}"."{1}" AS "{1}"nFROM "{2}"."{0}" "{0}"", matchingAddSelectPart.Table, matchingAddSelectPart.Column, schema)); } } if (element.Attribute("StoreEntitySet") != null && tableAndColumn.Any(oo => !oo.IsRemove && oo.Table == element.Attribute("StoreEntitySet").Value)) { var matchingAddSelectParts = tableAndColumn.Where(o => !o.IsRemove && o.Table == element.Attribute("StoreEntitySet").Value); foreach (var matchingAddSelectPart in matchingAddSelectParts) { element.Add(new XElement(element.GetDefaultNamespace() + "ScalarProperty", new XAttribute("Name", matchingAddSelectPart.Column), new XAttribute("ColumnName", matchingAddSelectPart.Column))); } } } } public static EntityConnection Create(List tablesAndColumns, string connString) { var modelNameRegex = new Regex(@".*metadata=res://*/([a-zA-Z.]*).csdl|.*"); var model = modelNameRegex.Matches(connString).Cast().SelectMany(o => o.Groups.Cast().Skip(1).Where(oo => oo.Value != "")).Select(o => o.Value).First(); var conceptualReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".csdl")); var mappingReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".msl")); var storageReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".ssdl")); var conceptualXml = XElement.Load(conceptualReader); var mappingXml = XElement.Load(mappingReader); var storageXml = XElement.Load(storageReader); foreach (var entitySet in new[] {storageXml, conceptualXml}.SelectMany(xml => xml.Elements())) { if (entitySet.Attribute("Name").Value == "ModelStoreContainer") { foreach (var entityContainerEntitySet in entitySet.Elements()) { ModifyNodes(entityContainerEntitySet, tablesAndColumns); } } ModifyNodes(entitySet, tablesAndColumns); } foreach (var entitySet in mappingXml.Elements().ElementAt(0).Elements()) { if (entitySet.Name.LocalName == "EntitySetMapping") { foreach (var entityContainerEntitySet in entitySet.Elements().First().Elements()) { ModifyNodes(entityContainerEntitySet, tablesAndColumns); } } ModifyNodes(entitySet, tablesAndColumns); } var storageCollection = new StoreItemCollection(new [] {storageXml.CreateReader()}); var conceptualCollection = new EdmItemCollection(new[] { conceptualXml.CreateReader() }); var mappingCollection = new StorageMappingItemCollection(conceptualCollection, storageCollection, new[] {mappingXml.CreateReader()}); var workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(conceptualCollection); workspace.RegisterItemCollection(storageCollection); workspace.RegisterItemCollection(mappingCollection); var connectionData = new EntityConnectionStringBuilder(connString); var connection = DbProviderFactories .GetFactory(connectionData.Provider) .CreateConnection(); connection.ConnectionString = connectionData.ProviderConnectionString; return new EntityConnection(workspace, connection); } }
初始化:
public ActionResult QUOTE_HOUSE() { var onlineDocs = Enumerable.Empty(); var mappings = new List{new SagaSystemToDatabaseMapping("x", "Oracle", "Db1", "metadata=res://*/Ecom.Ecom.csdl|res://*/Ecom.Ecom.ssdl|res://*/Ecom.Ecom.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string='...'", typeof(EcomEntities)) { ColumnsToModify = new List { new ColumnToAdd("QUOTE_HOUSE","TESTCOL", typeof(string)) } }}; var entityConnection = EntityConnectionExtensions.Create(mappings[0].ColumnsToModify,mappings[0].ConnectionString); using (var db = new EcomEntities(entityConnection)) { onlineDocs = db.QUOTE_HOUSE.Take(10); } return View("QUOTE_HOUSE", onlineDocs.ToList()); }
你应该能够从实体QUOTE_HOUSE
生成oracle数据库并输入一些虚拟值,不要认为你需要一个视图,因为它会爆炸.ToList()
。 生成数据库后,向数据库添加附加列但不alter table QUOTE_HOUSE add TESTCOL Varchar2(20)
模型( alter table QUOTE_HOUSE add TESTCOL Varchar2(20)
) – 使数据库中的列在运行时在模型中注入。 您可能还需要在此处调试EF程序集的方法 。 如果您需要更多信息或我错过了什么,请告诉我。
我知道这可能不是你所期待的,但我想至少它可以帮助你不浪费更多时间在那个方向。
好消息是问题不是由你的“hackish”代码引起的。 事实上,我能够在不使用该代码的情况下重现该问题。 刚刚创建了一个包含TestCol
的QUOTE_HOUSE
表,将其导入到新的edmx上下文中,只是从实体类中删除了生成的TestCol
属性。 然后我让这个类inheritance了DynamicEntity
,使用默认的构造函数创建了一个上下文,名为context.QUOTE_HOUSE.ToList()
,它用相同的exception爆炸了。
坏消息是你想要实现的目标是不可能的。 EF只使用映射“对象空间”成员的reflection。 它不提供任何类型的扩展机制,例如TypeDescriptor
,或动态运行时(它甚至不允许您投影到动态对象)。 后者是可以理解的,因为每个动态对象可能具有不同的属性,并且没有动态类型这样的东西。 请注意,在运行时“删除”列的技巧NotMapped
,因为它的作用基本上与在代码中首先使用NotMapped
相同,即属性确实存在,但被EF忽略。
如果您对实体在CSpace
但不在OSpace
中的原因感兴趣,则答案包含在名为OSpaceTypeFactory
的内部类(在System.Data.Entity.Core.Metadata.Edm
命名空间内) – 源中 。 有一个名为TryCreateStructuralType
的方法,它调用TryCreateMembers
,如果返回false
,则不添加类型。 TryCreateMembers
轮流调用TryFindAndCreatePrimitiveProperties
,传递使用reflection提取的PropertyInfo
列表,如果无法将任何 CSpace
成员映射到OSpace
对象属性,则后者返回false
,从而有效地防止将类型添加到OSpace
类型集合中。
希望至少能满足你的好奇心:)但是,再次,在运行时向EF实体“添加”属性是不幸的想法。
上述就是C#学习教程:entity framework实体不在DataSpace.OSpace(_workspace.GetItemCollection(DataSpace.OSpace))中,而是在DataSpace.CSpace中分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/984247.html