我有一个使用EntityFramework 6和SQL Server的数据库应用程序。 如果删除实体。我想向用户展示将与选定的一个对应于ON DELETE约束一起删除的每个相关实体。在实际删除之前。
所以我的问题是:
使用EntityFramework还是直接使用SQL Server特定查询来获取轻量级的可能性?
非常感谢您。
答案 0 :(得分:0)
此查询应为您提供所需的内容。在我的示例中,我找到了与“ Customers”表相关的所有表。
SELECT ParentTable.Name AS ParentTable, ChildTable.Name AS ChildTable
FROM sys.foreign_keys FK
INNER JOIN sys.tables ParentTable ON FK.parent_object_id = ParentTable.object_id
INNER JOIN sys.tables ChildTable ON FK.referenced_object_id = ChildTable.object_id
WHERE ParentTable.Name = 'Customers'
UNION
SELECT ParentTable.Name AS ParentTable, ChildTable.Name AS ChildTable
FROM sys.foreign_keys FK
INNER JOIN sys.tables ParentTable ON FK.parent_object_id = ParentTable.object_id
INNER JOIN sys.tables ChildTable ON FK.referenced_object_id = ChildTable.object_id
WHERE ChildTable.Name = 'Customers'
如果您不想将所有SQL都粘贴到解决方案中,则可以将该查询放入视图中
CREATE VIEW dbo.RelatedTables
AS
SELECT ParentTable.Name AS ParentTable, ChildTable.Name AS ChildTable
FROM sys.foreign_keys FK
INNER JOIN sys.tables ParentTable ON FK.parent_object_id = ParentTable.object_id
INNER JOIN sys.tables ChildTable ON FK.referenced_object_id = ChildTable.object_id
然后像表一样查询您的VIEW:
SELECT * FROM dbo.RelatedTables
WHERE ParentTable = 'Customers' OR ChildTable = 'Customers'
答案 1 :(得分:0)
我现在找到了解决我的问题的可行解决方案。以防万一其他人感兴趣。我将在此发布。它基于Eldho的评论。您可以使用实体框架获取依赖对象。如前所述,RelationshipManager已保存所有依赖对象。
我为DbContext写了两种扩展方法:一种使所有实体都依赖于给定实体。一种获得给定实体所依赖的所有实体的方法。
public static class DbContextExtensions
{
/// <summary>
/// Gets all entities the given entity is relying on.
/// Will cast the result to a given Type (Entity Base Class / Interface, whatever)
/// </summary>
public static List<TEntity> GetAllDependentEntities<TEntity>(this DbContext ctx, TEntity entity)
where TEntity : class
{
return ctx.GetAllRelatedEntities(entity, IsRelationshipParent);
}
/// <summary>
/// Gets all Entities relying on the given entity
/// Will cast the result to a given Type (Entity Base Class / Interface, whatever)
/// </summary>
public static List<TEntity> GetAllEntitiesDependingOn<TEntity>(this DbContext ctx, TEntity entity)
where TEntity : class
{
return ctx.GetAllRelatedEntities(entity, IsRelationshipChild);
}
private static List<TEntity> GetAllRelatedEntities<TEntity>(this DbContext ctx, TEntity entity, Func<IRelatedEnd, bool> relationshipFilter)
where TEntity : class
{
var result = new List<TEntity>();
var queue = new Queue<TEntity>();
queue.Enqueue(entity);
while (queue.Any())
{
var current = queue.Dequeue();
var foundDependencies = ctx.GetRelatedEntitiesFrom<TEntity>(current, relationshipFilter);
foreach (var dependency in foundDependencies)
{
if (!result.Contains(dependency))
queue.Enqueue(dependency);
}
result.Add(current);
}
return result;
}
private static List<TEntity> GetRelatedEntitiesFrom<TEntity>(this DbContext ctx, object entity, Func<IRelatedEnd, bool> relationshipFilter)
where TEntity : class
{
var stateManager = (ctx as IObjectContextAdapter)?.ObjectContext?.ObjectStateManager;
if (stateManager == null)
return new List<TEntity>();
if (!stateManager.TryGetRelationshipManager(entity, out var relationshipManager))
return new List<TEntity>();
return relationshipManager.GetAllRelatedEnds()
.Where(relationshipFilter)
.SelectMany(ExtractValues<TEntity>)
.Where(x => x != null)
.ToList();
}
private static IEnumerable<TEntity> ExtractValues<TEntity>(IRelatedEnd relatedEnd)
where TEntity : class
{
if (!relatedEnd.IsLoaded)
relatedEnd.Load();
if (relatedEnd is IEnumerable enumerable)
return ExtractCollection<TEntity>(enumerable);
else
return ExtractSingle<TEntity>(relatedEnd);
}
private static IEnumerable<TEntity> ExtractSingle<TEntity>(IRelatedEnd relatedEnd)
where TEntity : class
{
var valueProp = relatedEnd.GetType().GetProperty("Value");
var value = valueProp?.GetValue(relatedEnd);
yield return value as TEntity;
}
private static IEnumerable<TEntity> ExtractCollection<TEntity>(IEnumerable enumerable)
{
return enumerable.OfType<TEntity>();
}
private static bool IsRelationshipParent(IRelatedEnd relatedEnd)
=> relatedEnd.SourceRoleName.Contains("Target");
private static bool IsRelationshipChild(IRelatedEnd relatedEnd)
=> relatedEnd.TargetRoleName.Contains("Target");
}
或在此处查看:https://gist.github.com/felixalmesberger/8a9fde392698e366d5cbb75853efb412