13

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

我想要一种方法来查看是否CommonEntity可以安全地删除(即它不被任何其他实体使用)。

我意识到我能做到

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

但我希望有一种方法可以自动检查所有关系,因为我不喜欢每次添加新关系时都必须返回并手动更改此代码的想法。也许 EF4+ 中有一些我不知道的东西?

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

有更好的方法吗?

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

4

4 回答 4

13

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

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
    }
}
于 2012-10-12T06:13:04.340 回答
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
}
于 2012-10-12T04:49:05.450 回答
5

您可以为此使用反射(如果您不想使用“在 SQL 上删除失败”)我写这个是因为我不想删除实体,只是想知道它是否与任何相关!

 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;
}

请注意:不得释放上下文,必须启用代理,并且知道它将获取所有相关记录到内存中(它太重了)

于 2014-08-04T09:47:39.023 回答
-2

首先使用 EF 中的 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);
   }
于 2014-08-15T19:06:18.547 回答