【发布时间】:2016-09-04 00:29:09
【问题描述】:
问题总结:
- C# (MVC)、实体框架 5.0 和 Oracle。
- 我在连接两个表的视图中有几百万行。
- 我需要使用 filter-posibilities 填充下拉列表。
- 这些下拉列表中的选项应反映实际内容 该列的视图,不同的。
- 我想在您选择某些内容时更新下拉列表,所以 新选项反映过滤的内容,防止您 避免选择会产生 0 个结果的东西。
- 很慢。
问题:填充这些下拉列表的正确方法是什么?
现在了解更多详情。
-- 页面目标--
用户会看到一些下拉列表,这些下拉列表可以过滤下面网格中的数据。网格表示过滤结果的视图(参见“数据库”)。
每个下拉列表代表视图列的过滤器。一旦选择了某些内容,页面的其余部分就会更新。其他下拉列表现在包含其对应列的可能值,这些值符合刚刚在第一个下拉列表中应用的过滤器。
一旦用户选择了几个过滤器,他/她就会按下搜索按钮,下拉列表下方的网格会更新。
-- 数据库--
我有一个从两个表中选择几乎所有列的视图,没有什么特别的。像这样:
SELECT tbl1.blabla, tbl2.blabla etc etc
FROM table1 tbl1, table2 tbl2
WHERE bsl.bvz_id = bvz.id AND bsl.einddatum IS NULL;
共有 22 列。 13 个 VARCHARS(大部分很小,1 - 20,其中一个的大小为 2000!),6 个日期和 3 个数字(其中一个大小为 38,其中一个大小为 15,2)。
表上有几个索引,其中有 WHERE 子句的相关 ID。
要知道的重要一点:我无法更改数据库。也许在这里和那里设置一个索引,但没什么大不了的。
-- 实体框架--
我在我的解决方案中创建了一个数据库优先 EDMX,并映射了视图。这两个表也都有类,但我需要它们两个的数据,所以我不知道我是否需要它们。从任一表中选择内容的问题是您无法应用一半的过滤,但也许有一些我还没有想到的聪明方法。
-- 查看--
我的视图与视图模型紧密绑定。在那里,每个下拉列表都有一个 IEnumerable。这些的 getter 从名为 NameOfViewObjects 的单个 IEnumerable 中获取其数据。像这样:
public string SelectedColumn1{ get; set; }
private IEnumerable<SelectListItem> column1Options;
public IEnumerable<SelectListItem> Column1Options
{
get
{
if (column1Options == null)
{
column1Options= NameOfViewObjects.Select(item => item.Column1).Distinct()
.Select(item => new SelectListItem
{
Value = item,
Text = item,
Selected = item.Equals(SelectedColumn1, StringComparison.InvariantCultureIgnoreCase)
});
}
return column1Options;
}
}
我尝试过的两种解决方案是:
- 1 - 选择下拉列表所需的 linq 查询中的所有列(2000 varchar 不是其中之一,并且只有 2 个日期列),对它们执行不同的操作并将结果放入 Hashset。然后我设置 NameOfViewObjects 指向这个哈希集。我必须等待大约 2 分钟才能完成,但在那之后,填充下拉列表几乎是即时的(可能每个都需要一秒钟)。
model.Beslissingen = new HashSet<NameOfViewObject>(dbBes.NameOfViewObject
.DistinctBy(item => new
{
item.VarcharColumn1,
item.DateColumn1,
item.DateColumn2,
item.VarcharColumn2,
item.VarcharColumn3,
item.VarcharColumn4,
item.VarcharColumn5,
item.VarcharColumn6,
item.VarcharColumn7,
item.VarcharColumn8
}
)
);
这里最大的问题是对象 NameOfViewObject 可能非常大,即使在此处使用 distinct,导致不到 100.000 个结果,它仍然使用超过 500mb 的内存。这是不可接受的,因为会有很多用户使用这个屏幕(很多用户会...最多 10 个,同时平均 5 个)。
- 2 - 另一种解决方案是使用相同的 linq 查询并将 NameOfViewObjects 指向它产生的 IQueryable。这意味着每次视图想要将下拉列表绑定到 IEnumerable 时,它都会触发一个查询,该查询将在具有数百万行的表中找到该列的不同值,其中最有可能的是它从中获取值的列没有被索引.每个下拉列表(我有 10 个)大约需要 1 分钟,因此需要很长时间。
不要忘记:每次下拉列表的选择发生变化时,我都需要更新它。
-- 问题-- 所以我可能走错了路,或者也许这些解决方案之一应该与索引我使用的所有列相结合,也许我应该使用另一种方式将数据存储在内存中,所以它只是一点点,但是一定有人以前做过这件事并想出了一些聪明的办法。您能告诉我处理这种情况的最佳方法是什么吗?
可接受的性能:
- 页面加载时必须等待一段时间(2 分钟),但 之后一切都很快。
- 每次下拉列表都必须等待几秒钟 变化
- 页面使用的内存不超过 500mb
【问题讨论】:
-
如果屏幕上有很多用户怎么办。该列表存储在客户端上。你所拥有的满足你可以接受的表现。
-
您要在服务器上运行它并为每个用户单独设置?我帮不了你。
-
@JonKoeter 正如其他人所说,我认为您需要重新审视您的用户界面设计。您也许可以考虑以自动完成方式使用 ajax 为下拉列表提供服务。
-
那还是需要查询整个表不是吗?还是我误解了你的建议?
-
当你想要大数据集的速度时,缓存是唯一的选择,你必须用存储来换取速度,
标签: c# .net oracle entity-framework large-data