C# EF Query:Give.Contains()从数据库获取信息时要处理的两个元素的组合
我试图优化以下方法,让它只返回程序实际计算所需的数据。在过去,数据集没有那么大,所以我不需要对其进行太多优化。最近,我的数据集从大约30k条记录增长到700k条记录,所以我正试图进一步优化它C# EF Query:Give.Contains()从数据库获取信息时要处理的两个元素的组合,c#,sql,linq,entity-framework-4,C#,Sql,Linq,Entity Framework 4,我试图优化以下方法,让它只返回程序实际计算所需的数据。在过去,数据集没有那么大,所以我不需要对其进行太多优化。最近,我的数据集从大约30k条记录增长到700k条记录,所以我正试图进一步优化它 public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKey) { log.Info("Reading in raw th
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKey)
{
log.Info("Reading in raw thresholds from db");
using (FAI db= new FAI ())
{
rawThresholds = (from thr in db.Thresholds
where thr.CalculatedDate == maxDateTimeVal
where thr.ErrorSourceId == inputtedESourceID
where hashKey.Contains(thr.HashKey)
select thr).ToList();
}
log.Info("Read in " + rawThresholds.Count() + " threshold records for error source id: " + inputtedESourceID + ".");
}
但它因{System.NotSupportedException:无法创建“RTM_DB.HashKeyHostId”类型的常量值而出错。在此上下文中仅支持基元类型('例如Int32、String和Guid')
可能有一种非常简单的方法,我没有想到
是的,有
where hashKey.Contains(someValue) && hashKey.Contains(someOtherValue)
沿着这条路走也许就是你想做的
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKeys, List<int> hostIds)
{
log.Info("Reading in raw thresholds from db");
using (var db = new FAI())
{
var rths = (from thr in db.Thresholds
where thr.CalculatedDate == maxDateTimeVal
&& thr.ErrorSourceId == inputtedESourceID
select thr);
if (hashKeys != null && hashKeys.Count() > 0)
rths = rths.Where(rth => hashKeys.Contains(rth.HashKey))
if (hostIds != null && hostIds.Count() > 0)
rths = rths.Where(rth => hostIds.Contains(rth.HostId)) // FieldName?
rawThresholds = rths.ToList();
}
log.Info("Read in " + rawThresholds.Count() + " threshold records for error source id: " + inputtedESourceID + ".");
}
如果你有
List<HashKeyHostId> data = new List<HashKeyHostId>() {
new HashKeyHostId { hashKey = 100, hostId = 1 },
new HashKeyHostId { hashKey = 101, hostId = 5 }
}
请查看新编辑,了解我认为这不起作用的原因。@Migit我不是建议您将
hashKey
传递到两个Contains
调用中,您可以在其中传递您想要的任何内容。我回答的要点是向您展示如何在多属性检查的上下文中使用Contains
dit,您是否只需执行hashKey.hashKey.Contains(thr.hashKey)&&hashKey.hostId==thr.hostId
?您的第一个hashKey是HashKeyHostId对象的列表。您不能对对象执行.contains并将其转换为SQL。要使.contains使用LINQ转换为SQL,它需要是一个原语列表。您自己创建的对象列表将出现以下错误:“无法创建“RTM_DB.HashKeyHostId”类型的常量值。在此上下文中仅支持基本类型('例如Int32、String和Guid')。@Migit抱歉,我错过了我假设的hashKey
将是单个对象的内容。在这种情况下,检查只会变成hashKey.Any(x=>x.hashKey.Contains(thr.hashKey))&&x.hashKey.hostId==thr.hostId))
我会试一试。在过去,我遇到了很多问题。不过,我给它提供了非常大的数据集和。有人喜欢错误地说它嵌套太深。我相信你的建议与James的建议是一样的。我认为这行不通。它需要指定哈希键和HostID的组合,而不是任何组合两者的组合。请参阅新的编辑。添加了一个解决方案,您可以在这种情况下使用,因为您的两个键都是整数。我的哈希键实际上占据了int32的全部范围,因此我无法直接使用此方法。我尝试将所有内容强制转换为双精度,但显然没有与Convert.ToDouble()等效的linq由于这是一个错误:where filter.Contains(Convert.ToDouble(thr.ParentErrorSignatureHashKey)*100000.0+Convert.ToDouble(thr.HostId))与System.NotSupportedException异常我将其更改为where filter.Contains((double)(thr.ParentErrorSignatureHashKey)*100000.0+(double)(thr.HostId))虽然这看起来确实有效,但运行时间太长。它已经运行了4分钟,但仍然没有返回。如果我在该字段中查看,它可能会运行得更快,但我会等待其他人是否有响应,然后再执行此路线。使用Int64s进行尝试,也比不使用filt花费更多时间ering.这不会因为HashKeyHostId
无法翻译而失败吗?或者包含的是否做了一些其他方法没有做的聪明的事情?请参见编辑4。失败的原因与James建议的原因相同。Janne的建议听起来很棒,直到我看到运行时:(如果类型是POCO,并且您使用对象初始值设定项语法,则查询会将其理解为一个属性集合。这也可以通过匿名类型来完成。@Migit您必须使用EF,而不是linq to sql.well crap。我键入了其中的%#@*。是的,它使用的是EF
where hashKey.Contains(someValue) && hashKey.Contains(someOtherValue)
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKeys, List<int> hostIds)
{
log.Info("Reading in raw thresholds from db");
using (var db = new FAI())
{
var rths = (from thr in db.Thresholds
where thr.CalculatedDate == maxDateTimeVal
&& thr.ErrorSourceId == inputtedESourceID
select thr);
if (hashKeys != null && hashKeys.Count() > 0)
rths = rths.Where(rth => hashKeys.Contains(rth.HashKey))
if (hostIds != null && hostIds.Count() > 0)
rths = rths.Where(rth => hostIds.Contains(rth.HostId)) // FieldName?
rawThresholds = rths.ToList();
}
log.Info("Read in " + rawThresholds.Count() + " threshold records for error source id: " + inputtedESourceID + ".");
}
var filters = new int[] { 100 * 100 + 1 , 101 * 100 + 5 }; // 10001 & 10105
var rths = (from rth in db.Thresholds
where rth.CalculatedDate == maxDateTimeVal
&& rth.ErrorSourceId == inputtedESourceID
&& filters.Contains(rth.HashKey * 100 + rth.HostId)
select rth).ToList();
List<HashKeyHostId> data = new List<HashKeyHostId>() {
new HashKeyHostId { hashKey = 100, hostId = 1 },
new HashKeyHostId { hashKey = 101, hostId = 5 }
}
<somequery>.Where(x => data.Contains(new HashKeyHostId { hashKey = x.HashKey, hostId = x.HostId }))
WHERE ([t0].[HashKey] = @p0 AND [t0].[HostId] = @p1) OR
([t0].[HashKey] = @p2 AND [t0].[HostId] = @p3) OR ...