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

Ben*_*nC3 11 .net c# asp.net-mvc entity-framework entity-framework-4

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

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

我意识到我能做到

if(!ce.EntityA.Any() && !ce.EntityB.Any() ... && !ce.EntityN.Any())
{
   //Delete
}
Run Code Online (Sandbox Code Playgroud)

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

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

有更好的方法吗?

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

y34*_*34h 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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果ondeletecascade打开了怎么办?那它就不会失败了,不是吗? (2认同)

小智 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
}
Run Code Online (Sandbox Code Playgroud)


mX6*_*X64 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;
}
Run Code Online (Sandbox Code Playgroud)

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