将查询投影到匿名字典<string,int>

Project a Query onto an anonymous Dictionary<string,int>

我正在尝试检查数据库中的实体是否有任何外键关系,以便我可以通知用户可以或不能删除该实体。

我知道这可以在回滚事务中完成,但是我想告知用户有多少引用以及它们在何处以帮助他们决定删除实体。

我试图避免将整个导航集合加载到内存中以获取此数据,因为它可能很大。所以,鉴于此,我可以制定这个简单的查询来首先确定是否有任何引用:

private bool CanDeleteComponent(int compId)
{
    var query = _Context.Components.Where(c => c.ComponentID == compId)
        .Select(comp => new
        {
            References = comp.Incidents.Any() &&
            comp.Drawings.Any() &&
            comp.Documents.Any() &&
            comp.Tasks.Any() &&
            comp.Images.Any() &&
            comp.Instructions.Any()
        });
    var result = query.FirstOrDefault();
    if (result != null)
    {
        return !result.References;
    }
    return true;
}

这会执行一系列 SELECT COUNT(*) FROM <TABLE> WHERE... 查询。

现在,我想提供一些关于参考文献数量的进一步信息。理想情况下,我想 return 一个包含引用数据名称和相关计数的字典。这样我就可以遍历结果,而不是访问匿名类型的各个属性。但是,我尝试的结果出现异常:

var query = _Context.Components.Where(c => c.ComponentID == compId)
        .Select(comp => new Dictionary<string, int>
        {
            {"Events", comp.Incidents.Count()},
            {"Drawings", comp.Drawings.Count()},
            {"Documents", comp.Documents.Count()},
            {"Tasks", comp.Tasks.Count()},
            {"Images", comp.Images.Count()},
            {"Instructions", comp.Instructions.Count()},
        });
    var result = query.FirstOrDefault();
    return query.Any(fk => fk.Value > 0);

引发的异常是:

A first chance exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll
Additional information: Only list initializer items with a single element are supported in LINQ to Entities.

有没有办法解决这个问题,这样我就可以 return 某种 IEnumerable 而不是匿名类型?

谢谢

编辑 我目前在我的上下文中禁用了延迟加载。如果有没有开启延迟加载的解决方案,我们将不胜感激。

您不能在 SELECT 语句中构建 Dictionary<K,V>,这就是您得到 System.NotSupportedException 的原因。可以先查询得到单个Component,然后在内存中建字典

var comp = _Context.Components.SingleOrDefault(c => c.ComponentID == compId);
var dict = new Dictionary<string, int>()
{
    { "Events", comp.Incidents.Count()},
    { "Drawings", comp.Drawings.Count()},
    { "Documents", comp.Documents.Count()},
    { "Tasks", comp.Tasks.Count()},
    { "Images", comp.Images.Count()},
    { "Instructions", comp.Instructions.Count()}
};

EDIT 如果你没有使用延迟加载,你可以明确地 .Include 查询中的属性:

var comp = _Context.Components
    .Include(c => c.Incidents)
    ...
    .SingleOrDefault(c => c.ComponentID == compId);

Is there any way around this, such that I can return some sort of IEnumerable rather than an anonymous type?

实际上有,虽然我不确定你会喜欢生成的SQL(与使用匿名类型的相比)。

var query = _Context.Components.Where(c => c.ComponentID == compId)
    .SelectMany(comp => new []
    {
        new { Key = "Events", Value = comp.Incidents.Count() },
        new { Key = "Drawings", Value = comp.Drawings.Count() },
        new { Key = "Documents", Value = comp.Documents.Count() },
        new { Key = "Tasks", Value = comp.Tasks.Count() },
        new { Key = "Images", Value = comp.Images.Count() },
        new { Key = "Instructions", Value = comp.Instructions.Count() },
     }.ToList());

var result = query.ToDictionary(e => e.Key, e => e.Value);

return query.Any(fk => fk.Value > 0);