使用 GetProperties 时如何区分 Navigation Properties 与常规 Navigation Properties?
How to distinguish Navigation Properties from regular ones when using GetProperties?
有没有办法在实体框架 class(数据库优先)上区分常规集合 属性 和导航 属性?
我目前正在检查对象 is ICollection
和 IsVirtual
,但我觉得这可能会在有人声明为虚拟集合的常规 属性 上触发。
问题:还有其他方法可以区分导航属性吗?
Context:我用它来比较任何对象的值,但我希望它忽略导航属性(忽略循环引用等)。
foreach (var item in (IEnumerable)obj)
{
list2.MoveNext();
var item2 = list2.Current;
foreach (PropertyInfo propInfo in item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
Object v1 = propInfo.GetValue(item);
Object v2 = propInfo.GetValue(item2);
Primitive = (v1 == null && v2 == null) || IsPrimitive(v1.GetType());
if (Primitive)
{
Assert.AreEqual(v1, v2);
}
else
{
// Ignore Navigation Properties
// Currently assuming Virtual properties to be Navigation...
if (propInfo.GetGetMethod().IsVirtual) continue;
CompareObjects(v1, v2);
}
}
}
好吧,如果您想知道与实体相关的导航属性和标量属性的名称,我建议您使用此代码:
using (var db = new YourContext())
{
var workspace = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace;
var itemCollection = (ObjectItemCollection)(workspace.GetItemCollection(DataSpace.OSpace));
var entityType = itemCollection.OfType<EntityType>().Single(e => itemCollection.GetClrType(e) == typeof(YourEntity));
foreach (var navigationProperty in entityType.NavigationProperties)
{
Console.WriteLine(navigationProperty.Name);
}
foreach (var property in entityType.Properties)
{
Console.WriteLine(property.Name);
}
}
使用 GetProperties() 时的一个解决方案是创建一个 IEntity 接口并将其应用于所有实体。然后您可以通过检查它们是否实现 IEntity 和多实体导航来跳过单个实体导航属性
如果它们是 ICollection 类型。
所以在你的 foreach 中,
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>)) continue;
if (property.PropertyType.GetInterfaces().Contains(typeof(IEntity))) continue;
这是一个简单的方法 return 使用此逻辑仅更新属性:
private IEnumerable<PropertyInfo> GetUpdateableProperties<T>(T entity) where T : IEntity
{
return entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty)
.Where(property =>
property.CanWrite &&
!property.PropertyType.GetInterfaces().Contains(typeof(IEntity)) &&
!(property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
);
}
有没有办法在实体框架 class(数据库优先)上区分常规集合 属性 和导航 属性?
我目前正在检查对象 is ICollection
和 IsVirtual
,但我觉得这可能会在有人声明为虚拟集合的常规 属性 上触发。
问题:还有其他方法可以区分导航属性吗?
Context:我用它来比较任何对象的值,但我希望它忽略导航属性(忽略循环引用等)。
foreach (var item in (IEnumerable)obj)
{
list2.MoveNext();
var item2 = list2.Current;
foreach (PropertyInfo propInfo in item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
Object v1 = propInfo.GetValue(item);
Object v2 = propInfo.GetValue(item2);
Primitive = (v1 == null && v2 == null) || IsPrimitive(v1.GetType());
if (Primitive)
{
Assert.AreEqual(v1, v2);
}
else
{
// Ignore Navigation Properties
// Currently assuming Virtual properties to be Navigation...
if (propInfo.GetGetMethod().IsVirtual) continue;
CompareObjects(v1, v2);
}
}
}
好吧,如果您想知道与实体相关的导航属性和标量属性的名称,我建议您使用此代码:
using (var db = new YourContext())
{
var workspace = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace;
var itemCollection = (ObjectItemCollection)(workspace.GetItemCollection(DataSpace.OSpace));
var entityType = itemCollection.OfType<EntityType>().Single(e => itemCollection.GetClrType(e) == typeof(YourEntity));
foreach (var navigationProperty in entityType.NavigationProperties)
{
Console.WriteLine(navigationProperty.Name);
}
foreach (var property in entityType.Properties)
{
Console.WriteLine(property.Name);
}
}
使用 GetProperties() 时的一个解决方案是创建一个 IEntity 接口并将其应用于所有实体。然后您可以通过检查它们是否实现 IEntity 和多实体导航来跳过单个实体导航属性 如果它们是 ICollection 类型。
所以在你的 foreach 中,
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>)) continue;
if (property.PropertyType.GetInterfaces().Contains(typeof(IEntity))) continue;
这是一个简单的方法 return 使用此逻辑仅更新属性:
private IEnumerable<PropertyInfo> GetUpdateableProperties<T>(T entity) where T : IEntity
{
return entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty)
.Where(property =>
property.CanWrite &&
!property.PropertyType.GetInterfaces().Contains(typeof(IEntity)) &&
!(property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
);
}