【问题标题】:How To Process Entity Framework Context int Lambda Expression如何处理实体框架上下文 int Lambda 表达式
【发布时间】:2017-04-11 07:54:34
【问题描述】:

我使用 ef 6.13 获取一些数据,并将新的类数据返回到我的应用程序。

public List<v_apply_detail2> GetApplyList()
{
    using (yoyoEntities ds = new yoyoEntities())
    {
        return  datas = ds.v_apply_detail.Select(p => new v_apply_detail2 { apply_id = p.apply_id, time_line = ds.yoyo_apply_timeline.ToList() }).ToList();
    }
}

运行正常。
并且我想在 New Func 中移动 Select 方法,并使用 dbcontext yoyoEntities(ds)。

Func<v_apply_detail, v_apply_detail2> SelectOutApply(yoyoEntities ds, bool includetimeline = false)
{
    return (p => new v_apply_detail2
    {
        apply_id = p.apply_id,
        time_line = includetimeline ? ds.yoyo_apply_timeline.Where(x => x.apply_id == p.apply_id).OrderByDescending(x => x.time).ToList() : null
    });

}

public List<v_apply_detail2> GetApplyList()
{
    using (yoyoEntities ds = new yoyoEntities())
    {
        return  datas = ds.v_apply_detail.Select(SelectOutApply(ds,true)).ToList();
    }
}

当我调用 GetApplyList 函数时,它得到一个错误:实体框架:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭。

如何在 Func 或 Expression 中使用 dbcontext? 伙计们想想吧!

【问题讨论】:

  • 为什么不尝试将查询而不是数据上下文传递给函数?
  • 同意@AmanvirSinghMundra,您正在为两个不同的数据集“同时”在 Select 中执行 Where。 EF 正在尝试同时访问数据库
  • 我需要为不同的请求返回不同的数据,并且我有一些功能具有相同的查询,所以我需要通用的 Select Func。

标签: c# entity-framework lambda


【解决方案1】:

允许多个活动结果集应该可以解决您看到的错误。

string connectionString = "Data Source=MSSQL1;" +   
"Initial Catalog=AdventureWorks;Integrated Security=SSPI;" +  
"MultipleActiveResultSets=True";  

https://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.110).aspx

但我相信您应该传递可查询而不是 dbcontext。

更新: 将 Timeline 属性设为虚拟

public partial class v_apply_detail2 {
public long apply_id { get; set; }
public long hiring_id { get; set; }
public string hiring_title { get; set; }
public string publish_user_id { get; set; }
public string publish_company_id { get; set; }
public string user_id { get; set; }
public Nullable<System.DateTime> pre_accept_time { get; set; }
public sbyte join_type { get; set; }
public Nullable<decimal> deal_pay { get; set; }
public Nullable<System.DateTime> deal_time { get; set; }
public Nullable<System.DateTime> start_work_time { get; set; }
public Nullable<System.DateTime> finish_time { get; set; }
public string master_appraise { get; set; }
public string worker_appraise { get; set; }
public Nullable<int> master_rating { get; set; }
public Nullable<int> worker_rating { get; set; }
public int status { get; set; }
public Nullable<System.DateTime> master_rating_time { get; set; }
public Nullable<System.DateTime> worker_rating_time { get; set; }
public string hiring_snapshots { get; set; }
public virtual List<yoyo_apply_timeline> time_line { get; set; }
public member_info member_info { get; set; }
public company_info company_info { get; set; }}

然后不要使用上下文,而是使用查询变量:

Func<v_apply_detail, v_apply_detail2> SelectOutApply(yoyoEntities ds, bool includetimeline = false) {
return (p => new v_apply_detail2
{
    apply_id = p.apply_id,
    time_line = includetimeline ? p.timeline.OrderByDescending(x => x.time) : null
});}

更好的方法(单一方法): 为了简单起见,下面应该可以正常工作(只是不要使用 datacontext 再次查询时间线):

public List<apply_detail_dto> GetApplyList(){
using (yoyoEntities ds = new yoyoEntities())
{
    return  datas = ds.v_apply_detail.Select(p => new apply_detail_dto { apply_id = p.apply_id, time_line = p.timeline }).ToList();
}}

并使用 DTO 对象投影到(新的 apply_detail_dto {})。 希望对您有所帮助。

【讨论】:

  • 我的数据库是 mysql,没有 MultipleActiveResultSets 选项,
    我将这个可查询的“v_apply_detail”传递给我的 Func,但我需要相同的 dbcontext 来提高查询性能。
  • 也许急切加载会有所帮助。 bgsoftfactory.net/…。 “据我所知,MySql 没有任何可比的功能。所以我们必须使用 Eager Loading,即 Entity Framework 将中继我们告诉他如何加载相关数据。注释代码显示了第一种方法,带有 .Include ,而工作代码显示了第二种方法,使用 .ToList()。要查看延迟加载会发生什么,请删除“.ToList()”和括号,然后重新启动应用程序。”
  • 你没有提到你的 POCO 类的结构。但我会假设 v_apply_Detail 和 yoyo_apply_timelines 之间存在关系。因此,不要使用数据库上下文,而是使用导航属性。在 TimeLine 上添加 ToList() 也会触发查询。尝试删除它,因为您已经在 GetApplyList() 中这样做了。
【解决方案2】:

这可能对你有帮助

    Expression<Func<v_apply_detail, v_apply_detail2>> SelectOutApply(yoyoEntities ds,bool includetimeline = false)
    {
        if (includetimeline)
            return (p) => new v_apply_detail2
            {
                apply_id = p.apply_id,
                time_line = ds.yoyo_apply_timeline.Where(x => x.apply_id == p.apply_id).OrderByDescending(x => x.time).ToList() 
            };
        return (p) => new v_apply_detail2
            {
                apply_id = p.apply_id
            }; 

    }
    public List<v_apply_detail2> GetApplyList()
    {
        using (yoyoEntities ds = new yoyoEntities())
        {
            return datas = ds.v_apply_detail.Select(ds,SelectOutApply(true)).ToList();
        }
    }

【讨论】:

  • thanks。但是当includetimeline为true时仍然会导致以下错误:已经有一个打开的DataReader与此Connection关联,必须先关闭。
【解决方案3】:

感谢 Amanvir Singh Mundra。

这是我的 poco 课程

public partial class v_apply_detail2
{
    public long apply_id { get; set; }
    public long hiring_id { get; set; }
    public string hiring_title { get; set; }
    public string publish_user_id { get; set; }
    public string publish_company_id { get; set; }
    public string user_id { get; set; }
    public Nullable<System.DateTime> pre_accept_time { get; set; }
    public sbyte join_type { get; set; }
    public Nullable<decimal> deal_pay { get; set; }
    public Nullable<System.DateTime> deal_time { get; set; }
    public Nullable<System.DateTime> start_work_time { get; set; }
    public Nullable<System.DateTime> finish_time { get; set; }
    public string master_appraise { get; set; }
    public string worker_appraise { get; set; }
    public Nullable<int> master_rating { get; set; }
    public Nullable<int> worker_rating { get; set; }
    public int status { get; set; }
    public Nullable<System.DateTime> master_rating_time { get; set; }
    public Nullable<System.DateTime> worker_rating_time { get; set; }

    public string hiring_snapshots { get; set; }

    public List<yoyo_apply_timeline> time_line { get; set; }
    public member_info member_info { get; set; }
    public company_info company_info { get; set; }
}

我的项目中有相同的类来提供数据服务

所以,我的问题是查询性能和代码重用。

如果我在我的选择函数中添加 dbcontext,就像这样

using (yoyoEntities dd = new yoyoEntities())
{
    v_apply_detail2 result = new v_apply_detail2();
    {
        result.apply_id = x.apply_id;
        result.time_line = dd.yoyo_apply_timeline.Where(p => p.apply_id == x.apply_id).OrderByDescending(p => p.time).ToList();
    }
    return result;
}

我可以得到结果,但是触发了很多sql查询。 但是使用

return  datas = ds.v_apply_detail.Select(p => new v_apply_detail2 { apply_id = p.apply_id, time_line = ds.yoyo_apply_timeline.ToList() }).ToList();

sql查询只有一个。所以,我想重用ds。我认为表达式可以做到这一点,但我找不到路。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多