C# 使用GetProperties时如何区分导航属性和常规属性?

C# 使用GetProperties时如何区分导航属性和常规属性?,c#,entity-framework,reflection,C#,Entity Framework,Reflection,是否有办法区分实体框架类上的常规集合属性和导航属性(数据库优先) 我目前正在检查对象是否为ICollection和是否为virtual,但我觉得这可能会在有人声明为虚拟集合的常规属性上触发 问题:是否有其他方法将导航属性与其他属性区分开来 上下文:我用它来比较任何对象的值,但我希望它忽略导航属性(忽略循环引用等) 如果您想知道与实体相关的导航属性和标量属性的名称,我建议您使用以下代码: using (var db=new YourContext()) { var workspace =

是否有办法区分实体框架类上的常规集合属性和导航属性(数据库优先)

我目前正在检查对象
是否为ICollection
是否为virtual
,但我觉得这可能会在有人声明为虚拟集合的常规属性上触发

问题:是否有其他方法将导航属性与其他属性区分开来

上下文:我用它来比较任何对象的值,但我希望它忽略导航属性(忽略循环引用等)


如果您想知道与实体相关的导航属性和标量属性的名称,我建议您使用以下代码:

 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);
   }
}
使用(var db=new YourContext())
{
var workspace=((IObjectContextAdapter)db.ObjectContext.MetadataWorkspace;
var itemCollection=(ObjectItemCollection)(workspace.GetItemCollection(DataSpace.OSpace));
var entityType=itemCollection.OfType();
foreach(entityType.NavigationProperties中的var navigationProperty)
{
Console.WriteLine(navigationProperty.Name);
}
foreach(entityType.Properties中的var属性)
{
Console.WriteLine(property.Name);
}
}

使用GetProperties()的一个解决方案是创建一个Entity接口并将其应用于所有实体。然后,通过检查单个实体导航属性是否实现了多实体导航和多实体导航,可以跳过这些属性 如果它们属于ICollection类型

所以在你的演讲中

if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>)) continue;
if (property.PropertyType.GetInterfaces().Contains(typeof(IEntity))) continue;
如果(property.PropertyType.IsGenericType&&property.PropertyType.GetGenericTypeDefinition()==typeof(System.Collections.Generic.ICollection))继续;
如果(property.PropertyType.GetInterfaces().Contains(typeof(ienty)))继续;
下面是一个使用此逻辑仅返回可更新属性的简单方法:

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<>))
                );
    }
private IEnumerable GetUpdateableProperty(T实体),其中T:entity
{
返回entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty)
.Where(属性=>
property.CanWrite&&
!property.PropertyType.GetInterfaces()包含(typeof(ienty))&&
!(property.PropertyType.IsGenericType&&property.PropertyType.GetGenericTypeDefinition()==typeof(ICollection))
);
}

“是ICollection
。我不明白你想说什么?你的虚拟字符串属性检查将失败。哦,我不知道。这只是我需要更多了解导航属性的另一个原因,这样我才能更好地将它们与常规属性区分开来。这在某种程度上是可行的,但如果您有一个类具有一个
ICollection
,而不是一个导航属性,该怎么办呢。个人想象不出一个场景,但还是有些事情要考虑。还有单对象导航属性呢?我修改了答案来处理单对象导航。我不知道entity framework的实体属性如何成为ICollection accept for navigation属性,所以我不介意这样做。但您可以检查ICollection是否有效。
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<>))
                );
    }