我的实体之一不是代理

时间:2018-08-01 00:18:55

标签: c# entity-framework entity-framework-6

我收到的错误-

  

“ System.ArgumentException”类型的未处理异常发生在   mscorlib.dll

     

其他信息:值“ PHSRP_Dashboard.WorkSessionBreak”   不是类型   “ System.Data.Entity.DynamicProxies.WorkSessionBreak_06908 <.. many   个字符。> 6E3E”,并且不能在此通用集合中使用。

仅在新的WorkSessionBreak记录已添加到数据库时发生。对于仅被修改的记录不会发生,也不会在程序重新启动并且重新访问(不是这样)新记录时再次发生。

private void Edit_WorkSessionBreak_FormClosed(object sender, FormClosedEventArgs e)
{
    if (SelectedWorkSessionID >= 0)
    {
        var BreakSet = editEmployee.EmployeeWorkSessions
                                   .SelectMany(ws => ws.WorkSessionBreaks)
                                   .Where(b => b.DELETED != true && b.EmployeeWorkSessionID == SelectedWorkSessionID);

        if (BreakSet.Any())
        {
            var BreakSetSorted = BreakSet.OrderBy(b => b.OutTime);
            this.bs_WorkSessionBreaks_Display.DataSource = BreakSetSorted;        //  Blows-up on New record added.
        }
        else
        {
            this.bs_WorkSessionBreaks_Display.DataSource = new BindingList<WorkSessionBreak>();
        }
    }
    else
    {
        this.bs_WorkSessionBreaks_Display.DataSource = new BindingList<WorkSessionBreak>();
    }

    if (bs_WorkSessionBreaks_Display.Count > 0)
    {
        if (syncToViewBreak(((WorkSessionBreak)bs_WorkSessionBreaks_Display.Current).WorkSessionBreakID))
        {
            SelectedWorkSessionBreakID = ((WorkSessionBreak)bs_WorkSessionBreaks_Display.Current).WorkSessionBreakID;
        }
    }

    bs_WorkSessionBreaks_Display.ResetBindings(false); 
}

我们从中返回的对话框表单正常工作。更改/添加已正确放置在数据库中,但是与此父窗体关联的BindingSources不会自动重新排序。

对调试器中变量内容的检查表明,LINQ返回的Enumerable中的New记录是WorkSessionBreak,而其他先前存在的项目是WorkSessionBreak 代理

Debugger View 1

排序有效,但也返回类型和代理的混合:

Debugger View 2

下一条指令崩溃是因为一项与另一项的类型不同(即代理)。

Debugger View 3

我不知道该怎么办或为什么会发生。该算法可用于相同形式的其他部分,而不会发生此错误。

1 个答案:

答案 0 :(得分:1)

您面临的是deferred execution。基本上,代码试图将项目添加到数据库查询中。

这里:

var BreakSet = editEmployee.EmployeeWorkSessions
    .SelectMany(ws => ws.WorkSessionBreaks)
    .Where(b => b.DELETED != true 
             && b.EmployeeWorkSessionID == SelectedWorkSessionID);

BreakSetIQueryable<WorkSessionBreak>。每当您看到IQueryable<SomeClass>时,请记住它代表一个查询,(通常)不代表您存储在内存中的数据。

var BreakSet = editEmployee.EmployeeWorkSessions
   .SelectMany(ws => ws.WorkSessionBreaks)
   .Where(b => b.DELETED != true 
            && b.EmployeeWorkSessionID == SelectedWorkSessionID)
   .OrderBy(b => b.OutTime)
   .ToList();

if (BreakSet.Any())
{
    this.bs_WorkSessionBreaks_Display.DataSource = BreakSet;
}

有了这个,您现在有了一个数据库调用。 OrderBy子句不会影响COUNT查询的结果,因此您可以将其作为初始查询的一部分。注意,最后的ToList()调用是执行查询的对象,因此结果得以实现。