实体框架:检查实体的所有关系以供外键使用

时间:2012-10-12 01:59:24

标签: c# .net asp.net-mvc entity-framework entity-framework-4

我有一个实体,我们称之为CommonEntity,其主键在许多其他实体中用作外键。随着应用程序的开发,这些链接将继续增长。

我想知道是否可以安全删除CommonEntity(即任何其他实体都没有使用它)。

我意识到我能做到

if(!ce.EntityA.Any() && !ce.EntityB.Any() ... && !ce.EntityN.Any())
{
   //Delete
}

但是我希望能够自动检查所有关系,因为我不喜欢每次添加新关系时都必须手动更改此代码。也许EF4 +中有一些我不知道的东西?

我认为有可能使用事务范围来尝试删除对象并在其失败时将其回滚,但我不确定这种方法是否存在任何不良副作用。

有更好的方法吗?

编辑:看起来VS2012已使用EF5,即使该项目是.Net 4,因此它已经使用POCO创建了模型,即使它是从数据库生成的。

4 个答案:

答案 0 :(得分:11)

让它失败。如果实体有很多关系,那么验证可能非常繁重。

public bool TryDelete(int id)
{
    try
    {
        // Delete
        return true;
    }
    catch (SqlException ex)
    {
        if (ex.Number == 547) return false; // The {...} statement conflicted with the {...} constraint {...}
        throw; // other error
    }
}

答案 1 :(得分:5)

你可以试试这个:

var allrelatedEnds = ((IEntityWithRelationships)ce).RelationshipManager.GetAllRelatedEnds();
bool hasRelation = false;
foreach (var relatedEnd in allrelatedEnds)
{
    if (relatedEnd.GetEnumerator().MoveNext())
    {
        hasRelation = true;
        break;
    }
}

if (!hasRelation)
{
    //Delete
}

答案 2 :(得分:2)

你可以使用Reflection(如果你不想使用"在SQL&#34上删除失败;) 我写这个是因为我不想删除实体,只想知道它是否与任何相关!

 public static object GetEntityFieldValue(this object entityObj, string propertyName)
        {
            var pro = entityObj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).First(x => x.Name == propertyName);
            return pro.GetValue(entityObj, null);

        }

 public static IEnumerable<PropertyInfo> GetManyRelatedEntityNavigatorProperties(object entityObj)
        {
            var props = entityObj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanWrite && x.GetGetMethod().IsVirtual && x.PropertyType.IsGenericType == true);
            return props;
        }

public static bool HasAnyRelation(object entityObj)
        {

                var collectionProps= GetManyRelatedEntityNavigatorProperties(entityObj);


                foreach (var item in collectionProps)
                {
                    var collectionValue = GetEntityFieldValue(entityObj,item.Name);
                    if (collectionValue != null && collectionValue is IEnumerable)
                    {
                        var col = collectionValue as IEnumerable;
                        if (col.GetEnumerator().MoveNext())
                        {
                            return true;
                        }

                    }
                }
               return false;
}

注意:上下文不得处置,并且必须启用代理 并且知道它将获得所有相关的记录记录(它太重了)

答案 3 :(得分:-1)

首先使用Find中的Find查找要删除的实体,并将实体传递给下面的函数。如果函数返回true,则表示无法删除并且存在外来数据。如果函数返回false,则表示没有父项或子记录,可以删除..

 public static bool DeleteCheckOnEntity(object entity)
   {
     var propertiesList = entity.GetType().GetProperties();
     return (from prop in propertiesList where prop.PropertyType.IsGenericType select prop.GetValue(entity) into propValue select propValue as IList).All(propList => propList == null || propList.Count <= 0);
   }