Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 在WPF中缓存大量实体_.net_Wpf_Entity Framework_Caching - Fatal编程技术网

.net 在WPF中缓存大量实体

.net 在WPF中缓存大量实体,.net,wpf,entity-framework,caching,.net,Wpf,Entity Framework,Caching,我正在用WPF写一份申请书。我正在使用EntityFramework5,不知道您是否可以给我一些关于如何处理以下情况的建议 我基本上只有三张桌子: 项目{ID,Name} 属性{ID,名称,类型} AttributeValue{ItemID,AttributeID,Value} 我们的客户希望为他的物品添加属性,这似乎效果很好。现在,他可以添加属性并为其项指定值。第一个问题:你认为这是一个好的设计吗 现在的问题是如何在WPF数据网格中显示项,并将所有属性显示为列。这就是我们现在所拥有的: 我们以

我正在用WPF写一份申请书。我正在使用EntityFramework5,不知道您是否可以给我一些关于如何处理以下情况的建议

我基本上只有三张桌子:

项目{ID,Name}

属性{ID,名称,类型}

AttributeValue{ItemID,AttributeID,Value}

我们的客户希望为他的物品添加属性,这似乎效果很好。现在,他可以添加属性并为其项指定值。第一个问题:你认为这是一个好的设计吗

现在的问题是如何在WPF数据网格中显示项,并将所有属性显示为列。这就是我们现在所拥有的:

我们以编程方式生成列:

foreach (var attribute in db.Attributes)
{
    datagrid.Columns.Add(new DataGridTextColumn
    {
        Header = attribute.Name,
        Binding = new Binding { Path = new PropertyPath(string.Format("[{0}]", attribute.ID)) }
    });
}
这个很好用。现在的问题是如何在Items类中实现索引器。我们有一个选项,它在处理大量数据时速度非常慢(20000个项目,400个属性,每个项目有100个值):

就像我说的,这是可行的,但会变慢。我没有总是查询AttributeValue,而是在显示之前缓存所有内容,如下所示:

var items = db.Items.AsNoTracking().ToArray();
CachedValues.Values = new Dictionary<int, Dictionary<int, AttributeValue>>(items.Length);
foreach (var item in items)
{
    var attributevalues = db.AttributeValue.AsNoTracking().Where(w => w.ArtikelID == item.ID).ToArray();
    CachedValues.Values[item.ID] = new Dictionary<int, AttributeValue>(attributevalues.Length);
    foreach (var value in attributevalues)
    {
        CachedValues.Values[item.ID][value.AttributeID] = value;
    }
}
很明显,初始化缓存需要一些时间(15秒),但是速度要快得多。按datagrids中的属性对项目进行排序只需一秒钟。用另一种方法,它会持续很久

我对解决方案不满意,你有什么建议吗?我愿意接受任何形式的批评(我知道这两种批评都不是好的解决办法)

谢谢

托马斯

编辑

要使第一个问题更清楚,请举一个小例子:

项目:项目1、项目2、项目3,。。。 属性:宽度、高度、速度。。。 属性值:(项目1,宽度,100),(项目1,高度,200),(项目2,宽度,100),(项目3,高度,200),(项目3,速度,40)


所以这是一个经典的多对多关系。属性可能出现在0-many项中,而项可能具有0-many属性。

回答第一个问题:为什么属性和属性值不合并?AttributeValue可以有更多属性吗?我想这是一个可以有多个属性的项目

项目{ID,Name}

属性{ID,ItemID,Name,Type,Value}


我想给你们写一个问题的答案,但当我深入研究你们的问题时,我开始不确定你们在做什么。您正在尝试在数据库中创建动态表吗*

以下是我的回答:


您需要找出性能瓶颈所在。是检索数据还是显示数据

15秒对于显示的数据来说似乎太多了。这不应该超过1到2秒,IMHO

这里有几个提示:

DataGrid是一个很重的控件,可以做很多事情。我建议您将ListView与GridView结合使用,并根据您必须具备的任何需求对您进行自定义

默认情况下,ListView是虚拟化的。在4.0中,如果应用分组虚拟化,将禁用。在4.5中,可以应用分组虚拟化

使用SQL事件探查器优化数据库查询。查看执行了哪些查询。如果执行大量查询,可能会导致性能下降。在EF(with.Include)中进行快速加载有助于加快速度。记住正确的索引


要评论拉迪斯拉夫·姆卡的评论,这并不是全部真相。WPF控件不支持数据虚拟化(仅当显示数据时才获取数据)。它们只支持所有数据都存在的普通虚拟化,但只呈现项目的可视部分。两者之间有很大的区别。有一些解决方案试图在WPF中实现数据虚拟化

您的数据模型是一个非常通用的解决方案,有支持和反对它的观点,但是如果没有更多的背景,很难判断,所以我将跳过问题的这一部分

我可能已经实现了一个与您类似的缓存,但是做了一些轻微的修改

  • 我不会使用全局静态缓存,而是每个实体一个字典,只缓存该实体的属性值。这样,如果实体超出范围,您就不必关心从全局缓存中删除条目,因为缓存会与实体一起被垃圾收集

  • 我不会预先填充字典,而是首先尝试从缓存中获取值,如果不存在,则搜索属性值列表并根据需要更新缓存。如果应用程序表现良好,并且不能一次访问所有值(例如,因为在任何时候网格中只有一些数据可见,而其他行不可见),则这可能会在较长的时间内无缝地分布缓存填充过程,并使用户看不到它


最后一个想法-20000件物品,每个物品有400个属性?哪个用户应该能够处理一个一次最多显示8000000个值的应用程序?也许你也应该考虑重新设计用户界面和交互逻辑——没有人需要并且可以同时处理这么多信息。

嘿,只是一个简短的说明,一步一步地抓取每一件东西要快得多,而不是使用虚拟化控件来执行每一个属性的子查询。(或者在WPF中是如何调用的)。这意味着不要一次加载所有数据,而是加载例如100行,并在用户向下滚动时加载下一个100行。这就像没有页面列表的分页。WPF应该对此有一些支持。我正在使用DataGrid的虚拟化功能:(EnableColumnVirtualization=“True”,EnableRowVirtualization=“True”)在我看来,它们不应该被合并。我在我编辑的帖子中更详细地解释了它。我将查看ListVIEW和SQL Primerer.Exchange。我们今天改变了设计,并使用分页来向用户显示这些项目的一小部分。我将考虑缓存机制的想法。
var items = db.Items.AsNoTracking().ToArray();
CachedValues.Values = new Dictionary<int, Dictionary<int, AttributeValue>>(items.Length);
foreach (var item in items)
{
    var attributevalues = db.AttributeValue.AsNoTracking().Where(w => w.ArtikelID == item.ID).ToArray();
    CachedValues.Values[item.ID] = new Dictionary<int, AttributeValue>(attributevalues.Length);
    foreach (var value in attributevalues)
    {
        CachedValues.Values[item.ID][value.AttributeID] = value;
    }
}
public static class CachedValues
{
    public static Dictionary<int, Dictionary<int, ArtikelAttribut>> Values;
}
public AttributeValue this[int i]
{
    get
    {
        AttributeValue val = null;
        CachedValues.Values[ID].TryGetValue(i, out val);
        return val;
    }
}