我的代码类似于以下内容。
using (MyEntities context = new MyEntities())
{
var activities = from act in context.Activities
where act.ActTwittered == false
select new { act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location };
foreach (var activity in activities)
{
/* ... */
}
}
这似乎工作正常,但我的循环有很多处理。我担心在处理过程中我会打开数据库连接或其他资源。
我尝试在var activities
语句之前声明using
,以便我可以在using
语句之后处理数据,但是必须在声明它的地方初始化此变量。
了解EF内部工作原理的人是否可以告诉我,当EF上下文“活着”时,是否存在长时间处理的问题,以及我如何减轻这些问题。
虽然我很喜欢,但也许您也可以评论我在循环中使用act.Category.CatName
的事实。这是相关表格中的值。我最好在我的EF查询中使用连接,这样我就可以一次性获取数据而不是强制另一个(?)数据库访问来获取相关数据吗?
答案 0 :(得分:5)
您可以让编译器通过调用泛型方法来推断结果类型:
public static T CallFunc<T>( Func<T> theFunc )
{
return theFunc();
}
...
var activities = CallFunc( () =>
{
using( var context = new MyEntities() )
{
return
(
from act in context.Activities
where act.ActTwittered == false
select new { act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location };
)
.ToList();
}
} );
foreach( var a in activities ) ...
最后不要忘记.ToList()
,否则在您对其进行枚举之前,您的查询将不会被实际执行,这将在上下文关闭后发生。
答案 1 :(得分:2)
您的问题是希望匿名类型可以在其上下文之外访问。您可以为结果使用特定类型,并可以灵活地在任何地方访问值。
public class ActivitySummary
{
public int ActID { get; set; }
public string ActTitle { get; set; }
public string Category { get; set; }
public DateTime ActDateTime { get; set; }
public string Location { get; set; }
}
。 。
List<ActivitySummary> activities;
using (MyEntities context = new MyEntities())
{
activities = from act in context.Activities
where act.ActTwittered == false
select new ActivitySummary { act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location }.ToList();
}
foreach (var activity in activities)
{
/* ... */
}
答案 2 :(得分:1)
将读取和处理分开的最大问题是你的代码完全没有这样做。
第一个语句只创建一个能够获取数据的表达式,但它实际上并不提取任何内容。直到你开始阅读它才能获得任何数据。
在使用该代码处理数据之前,您需要做两件事才能关闭数据库连接。您必须使用ToList
方法实际获取数据而不是仅仅设置表达式,并且必须使用Dispose
而不是using
,这样您就不会将在其范围内的匿名类型:
MyEntities context = new MyEntities();
var activities = (
from act in context.Activities
where act.ActTwittered == false
select new { act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location }
).ToList();
context.Dispose();
foreach (var activity in activities) {
/* ... */
}
这种方法的一个缺点是你没有得到try...finally
提供的代码的隐式using
,所以如果在获取数据时出错,则上下文不会处置。
另一种方法是声明一个可以保存您读取的数据的类,以便您可以使用using
块之外的已知类声明变量:
List<Activity> activities;
using (MyEntities context = new MyEntities()) {
activities = (
from act in context.Activities
where act.ActTwittered == false
select new Activity(act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location)
).ToList();
}
答案 3 :(得分:1)
如果我需要长时间使用DB的结果,我通常会创建该特定类型,只需声明一个包含所需字段的类,而不是使用匿名类型,在从数据库获取数据后,我会生成一个线程我做了所需的工作。这样,与数据库的连接就会关闭,应用程序仍然会响应。
答案 4 :(得分:0)
您可以手动处理DataContext。
此外,您需要在查询上调用ToArray
,以便它立即执行(而不是在处理上下文后):
MyEntities context = new MyEntities();
var activities = (from act in context.Activities
where act.ActTwittered == false
select new { act.ActID, act.ActTitle, act.Category, act.ActDateTime, act.Location })
.ToArray();
context.Dispose();
//Do something with activities
但是,我建议您切换到非匿名类型,以便继续使用using
来处置上下文。
例如,using
即使发生异常也会小心调用Dispose
。