LINQ .FromSQL错误InvalidOperationException:Sequence包含多个匹配元素

时间:2017-07-28 03:44:32

标签: c# sql entity-framework linq

我在使用Entity Framework和linq从存储过程请求数据时引发了此异常。

error_reporting = E_ALL

堆栈的相关部分在这里(道歉它在两行,但堆栈溢出编辑器赢了,让我打破它而不留下代码块格式化):

An unhandled exception occurred while processing the request.

InvalidOperationException: Sequence contains more than one matching element
System.Linq.Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource> source, 
Func<TSource, bool> predicate)

错误源于使用.FromSql作为linq查询的一部分进行数据库调用。我这样调用数据 - 即使它有一个.ToListAsync(),堆栈跟踪也表明linq语句仍然在每个返回的订单项上调用.SingleOrDefault() - 我假设这是预期的:

System.Linq.Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource> source, 
Func<TSource, bool> predicate) Microsoft.EntityFrameworkCore.Query.Sql.Internal.FromSqlNonComposedQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader) Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized<TParam, TValue>(ref TValue target, TParam param, Func<TParam, TValue> valueFactory) Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader) Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable+AsyncEnumerator+<BufferlessMoveNext>d__9.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

返回的数据集是此视图所代表的平面数组:

[HttpPost, Route("GetOneWeekRosters")]
    public async Task<List<RosterLineView>> GetOneWeekRosters([FromBody] RosterSearch mysearch)
    {
        var dataentry = await _edb.RosterLineViews.FromSql("GetOneWeekRosters @Date, @DepartmentID, @RosterID, @RosterWeekID, @Active", new SqlParameter("@Date", mysearch.DateSelected), new SqlParameter("@DepartmentID", mysearch.DepartmentID), new SqlParameter("@RosterID", mysearch.RosterID), new SqlParameter("@RosterWeekID", mysearch.RosterWeekID), new SqlParameter("@Active", "true")).ToListAsync();
        return dataentry;
    }

此视图具有通过覆盖编码的复合键,如下所示:

 public class RosterLineView
{

    public int RosterLineID { get; set; }
    public int RosterID { get; set; }
    public int EmployeeID { get; set; }
    public int RosterShiftID { get; set; }
    public string RosterShiftName { get; set; }
    public string Notes { get; set; }
    public int RosterAreaID { get; set; }
    public string RosterAreaName { get; set; }
    public DateTime DateEntry { get; set; }
    public int RosterWeekID { get; set; }
    public DateTime RosterShiftStart { get; set; }
    public DateTime RosterShiftFinish { get; set; }
    public int ActivityTypeID { get; set; }
    public string ActivityTypeShort { get; set; }
    public decimal RosterHourValue { get; set; }
    public int PositionID { get; set; }
    public int DepartmentID { get; set; }
    public int InstitutionID { get; set; }
    public string FirstName { get; set; }
    public string Surname { get; set; }
    public decimal ContractedHours { get; set; }

}

我已经使用调用中提供的样本数据检查了存储过程结果,并且可以使用这些键确认数据中没有重复项,如果有人认为问题存在,那么很高兴PM样本数据集,但我也尝试过对这个程序进行明确的调用。

关于为什么它仍然可能会给出这个错误的任何想法,这听起来好像返回了重复的数据?虽然我认为给出异常的原因是,它是否可能与数据集无关,而是视图声明和复合键规范或其他什么?我最初确实在我删除的视图中有一个错误的[Key]注释,是否有可能以某种方式缓存,即使它被删除了?尝试调试4小时后,只是一些随机的想法。谢谢大家,感谢您的帮助。在未来几个小时内离开PC但我会在之后回复任何评论。

编辑 - 按照要求存储过程

modelBuilder.Entity<RosterLineView>()
            .HasKey(c => new { c.RosterLineID, c.DateEntry, c.EmployeeID, c.PositionID });

4 个答案:

答案 0 :(得分:5)

出现同样的问题,我注意到我为多个列使用了相同的列名。我检查了你的程序,似乎 RosterLineID 是重复的,这在某种程度上混淆了EF。每当出现此错误时,请务必检查列名称。希望这会有所帮助...

答案 1 :(得分:4)

有同样的问题;正在运行EF Core 2.1并调用存储过程。对我来说,问题出在存储过程中。我有一个带有内部联接的SELECT *,它正在返回两个表的结果。我将存储过程更改为仅返回所需的表,从而解决了该问题。

答案 2 :(得分:0)

这不是一个很好的答案,但我通过使用ADO.NET来获取数据集来获取存储过程。 SPROC确实有效,所以我认为真正的答案是某种方式的问题.net core 1.1使用linq返回其数据集,并且可能以它评估存储过程结果的方式。我没有时间来证明这一点,但目前我有数据和它的好处。它只需要另外50行代码就可以使用SqlConnection,SqlDataReader和SqlCommand手动生成集合。我创建了一个List,并使用While循环中的SqlDataReader迭代地将数据添加到它。

这是所有荣耀的痛苦:

 SqlConnection sqlconn = new SqlConnection("xxxxxxxxx");
        sqlconn.Open();
        SqlCommand sqlcomm = new SqlCommand("GetOneWeekRosters", sqlconn);
        SqlParameter a = new SqlParameter("@Date", mysearch.DateSelected);
        SqlParameter b = new SqlParameter("@DepartmentID", mysearch.DepartmentID);
        SqlParameter c = new SqlParameter("@RosterID", mysearch.RosterID);
        SqlParameter d = new SqlParameter("@RosterWeekID", mysearch.RosterWeekID);
        SqlParameter e = new SqlParameter("@Active", true);
        sqlcomm.Parameters.Add(a);
        sqlcomm.Parameters.Add(b);
        sqlcomm.Parameters.Add(c);
        sqlcomm.Parameters.Add(d);
        sqlcomm.Parameters.Add(e);
        sqlcomm.CommandType = CommandType.StoredProcedure;
        var rdr = await sqlcomm.ExecuteReaderAsync();
        var mylist = new List<RosterLineView>();
        while (rdr.Read()) {
            int rosterid = int.Parse(rdr["RosterID"].ToString());
            int rosterweekid = int.Parse(rdr["RosterWeekID"].ToString());
            string firstname = rdr["FirstName"].ToString();
            string surname = rdr["Surname"].ToString();
            int employeeid = int.Parse(rdr["EmployeeID"].ToString());
            int departmentid = int.Parse(rdr["DepartmentID"].ToString());
            int institutionid = int.Parse(rdr["InstitutionID"].ToString());
            decimal contractedhours = decimal.Parse(rdr["ContractedHours"].ToString());
            int reportingorder = int.Parse(rdr["ReportingOrder"].ToString());
            string notes = rdr["Notes"].ToString();
            int activitytypeid = int.Parse(rdr["ActivityTypeID"].ToString());
            string activitytypeshort = rdr["ActivityTypeShort"].ToString();
            decimal rosterhourvalue = decimal.Parse(rdr["RosterHourValue"].ToString());
            int rosterlineid = int.Parse(rdr["RosterLineID"].ToString());
            int positionid = int.Parse(rdr["PositionID"].ToString());
            DateTimeOffset shiftstart = DateTimeOffset.Parse(rdr["ShiftStart"].ToString());
            string rosterareaname = rdr["RosterAreaName"].ToString();
            string rostershiftname = rdr["RosterShiftName"].ToString();
            DateTimeOffset shiftfinish = DateTimeOffset.Parse(rdr["ShiftFinish"].ToString());
            int rostershiftid = int.Parse(rdr["RosterShiftID"].ToString());
            int rosterareaid = int.Parse(rdr["RosterAreaID"].ToString());
            DateTime datedim = DateTime.Parse(rdr["DateDim"].ToString());

            var myitem = new RosterLineView();
            myitem.RosterID = rosterid;
            myitem.RosterLineID = rosterlineid;
            myitem.RosterShiftFinish = shiftfinish;
            myitem.RosterShiftStart = shiftstart;
            myitem.ActivityTypeID = activitytypeid;
            myitem.ActivityTypeShort = activitytypeshort;
            myitem.ContractedHours = contractedhours;
            myitem.DateDim = datedim;
            myitem.DepartmentID = departmentid;
            myitem.InstitutionID = institutionid;
            myitem.Notes = notes;
            myitem.PositionID = positionid;
            myitem.RosterAreaID = rosterareaid;
            myitem.RosterAreaName = rosterareaname;
            myitem.RosterShiftID = rostershiftid;
            myitem.RosterShiftName = rostershiftname;
            myitem.Surname = surname;
            myitem.FirstName = firstname;
            myitem.RosterHourValue = rosterhourvalue;
            myitem.RosterWeekID = rosterweekid;
            mylist.Add(myitem);

        }

        sqlconn.Close();
        rdr.Dispose();
        return mylist;

    }

继续前进。

答案 3 :(得分:0)

检查结果列中是否有重复项。就我而言,这就是原因。如果您两次选择相同的列名,则存储过程将起作用,但是FromSql会抛出此异常。