C# 将查询投影到匿名词典<;字符串,int>;

C# 将查询投影到匿名词典<;字符串,int>;,c#,entity-framework,dictionary,ienumerable,C#,Entity Framework,Dictionary,Ienumerable,我试图检查数据库中的一个实体是否有任何外键关系,以便我可以通知用户该实体可以删除或不能删除 我知道这可以在回滚事务中完成,但是我想通知用户有多少引用以及它们将在何处帮助他们决定删除实体 我试图避免将整个导航集合加载到内存中以获取此数据,因为它可能很大。因此,有鉴于此,我可以制定这个简单的查询,首先确定是否有任何引用: private bool CanDeleteComponent(int compId) { var query = _Context.Components.Where(c

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

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

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

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;
}
这将执行一系列的
选择计数(*),其中…
查询

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

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);
是否有任何方法可以避免这种情况,这样我就可以返回某种IEnumerable而不是匿名类型

谢谢

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

您不能在
SELECT
语句中构建
字典,这就是为什么您会得到
System.NotSupportedException
。您可以先通过查询获得单个
组件
,然后在内存中构建字典

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()}
};
是否有任何方法可以避免这种情况,这样我就可以返回某种IEnumerable而不是匿名类型

实际上有,尽管我不确定您是否会喜欢生成的SQL(与使用匿名类型的SQL相比)


谢谢,如果我有LazyLoadingEnabled=true,我可以看出这会起作用。有没有办法关闭它?谢谢,但现在它会加载所有导航数据,这可能是相当大的内存密集型,这是我试图避免的。最终目标是只对每个FK执行
SELECT COUNT()
查询table@Simon尝试
。其中(xxx)。选择(comp=>new{Events=comp.Events.Count,Drawings=comp.Drawings.Count,Document=comp.Documents.Count,Tasks=comp.Tasks.Count,Images=comp.Images.Count,Instructions=comp.Instructions.Count})
谢谢Danny,在查询中似乎没有一种方法可以完成所有操作,所以这是下一个最好的方法。我无法实现这一点。对于初学者来说,在每个匿名对象之前放置
new
,示例才为我编译。其次,我得到了错误
数组类型'f_uAnonymousType1'2[System.String,System.Int32][]不能在查询结果中初始化。请考虑使用“Stry.Copys.Gual.List'1[fy-AuthOnouthSyp1’2[Stray.String,St.Int3]]'相反。
@erdomke您在每个数组元素之前的
新建
方面是正确的。如果您使用
Select
而不是
SelectMany
,则会出现异常。添加
ToList()
最后使它在
Select
SelectMany
中都能工作-请参阅更新。EF是奇怪的怪物:)您是对的,我设法掩饰了您对SelectMany的使用。该示例现在对我有效,但前提是我省略了新添加的ToList()。使用ToList,我得到
LINQ to Entities无法识别方法'System.Collections.Generic.List'1[f_uAnonymousType1'2[System.String,System.Int32]]ToList[f_uAnonymousType1'2](System.Collections.Generic.IEnumerable'1[f_uAnonymousType1'2[System.String,System.Int32]))'方法,此方法无法转换为存储表达式。
谢谢您的帮助!
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()}
};
var comp = _Context.Components
    .Include(c => c.Incidents)
    ...
    .SingleOrDefault(c => c.ComponentID == compId);
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);