繁体   English   中英

通过使用属性装饰属性来对集合进行排序。 (收藏检索通过反射触发)

[英]Sort Collection by decorating a property with an attribute. (collection retrieval is triggered through reflection)

我有一个包含ICollection的 object :

public abstract class Container : Component, IContainer
{        
    public virtual ICollection<Component> Components { get; set; }
    ...
    ...
}

由于它是虚拟的,因此Component将被延迟加载(当“获取” Component的属性时: myContainerInstance.Components )。

我们的应用程序严重依赖反射。 反射部分之一是检索某个 Container 的所有属性,循环遍历它并检索每个属性的值。 像这样的东西:

var props = type.GetProps();
foreach (var prop in props)
{
    var propValue = prop.GetValue(bo, null); // EF triggers lazy loading in case the prop is a virtual ICollection and immediately _materializes_ all the data
    ...
    ...
}

我正在尝试找到一种方法,如何让 EF 按指定顺序检索该数据。 这有可能吗? 我试图用谷歌搜索是否可以使用一个属性来装饰该集合属性,该属性将指示 EF 订购其检索的日期。 或者我太累了,找不到好的谷歌查询,或者不可能,或者......?

PS:禁用该属性的延迟加载不是一种选择,因为该集合中的某些Component s 本身就是Container s。 这会导致大量的 select 语句。 整个 object 结构理论上可以包含无限深度(现实是 - 目前 - 最多 4 个)

据我所知,这是不可能的。

在 ObjectContext API 中,可以通过从导航属性创建查询来显式加载,但必须关闭延迟加载,因为一旦启用延迟加载,对集合属性的任何访问都会立即触发加载,因此显式加载将再次加载数据。 即使打开了延迟加载,DbContext API 也应该能够使用显式加载。 仍然显式加载意味着您必须手动调用某些方法/查询来加载属性。

这是我最后所做的(简化版):

var propValue = prop.GetValue(bo, null); // this (in case the `prop` is a virtual `ICollection<Component>`) lazy loads all components, returning them not always in the same order (due to paralelism on sql server?))
if (prop.PropertyType.IsGenericType)
{
    ...
    if (prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    {
        ...        
    }
    else if (innerType.IsSubclassOfOrEquivalentTo(typeof(Component)) && propValue != null)
    {
        // order the list of components in memory into a new variable
        var listOfComponents = ((IEnumerable) propValue).Cast<Component>().OrderBy(c => c.ComponentId);            

        dynamic componentsHash = propValue; // I had to use dynamic, because sometimes the propValue was an List<...>, sometimes a HashSet<...>, sometimes a ...
        componentsHash.Clear(); // empty the collection retrieved by EF

        int componentCount = listOfComponents.Count;
        for (var i = 0; i < componentCount; i++)
        {
            var component = listOfComponents[i];
            componentsHash.Add(component); // re-add components to the collection
            ...
        }
        // at this point the collection object contains ordered dynamic proxy objects (attached EF objects)
    }
    else
    {
        ...
    }
}
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM