2017-07-28 136 views
0

我有使用实体框架和LINQ从存储过程中请求数据时引发此异常。LINQ .FromSQL错误InvalidOperationException:序列包含多个匹配元素

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) 

堆栈的相关部分是在这里(道歉了两行,但堆栈溢出的编辑不会让我打破它,没有它离开代码块格式):

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() 

的错误是由使用.FromSql作为linq查询的一部分的数据库调用产生的。我像这样调用数据 - 尽管它具有.ToListAsync()堆栈跟踪指示linq语句仍然调用每个行项目上的.SingleOrDefault() - 我假设这是打算:

[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; } 

} 

这一观点复合键通过如下重写编码:

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

我已经EXA使用调用中提供的示例数据挖掘存储过程结果,并且可以确认使用这些密钥的数据中没有重复项,如果有人认为问题存在,那么很高兴能够访问示例数据集,但是我已尝试使用程序。

任何想法,为什么它仍然可能会给这个错误,这使得它听起来像有重复的数据被返回?虽然我假设这是给出例外的原因,是否有可能它不涉及数据集,但视图声明和组合键规范或什么?我最初确实在视图中有一个错误的[Key]注释,我删除了,是否有可能以某种方式缓存了它,即使它被删除了?尝试调试4小时后,只是一些随机想法。谢谢你,感谢你的帮助。远离个人电脑在接下来的几个小时,但我会回来后的任何意见。

编辑 - 这里的存储过程的要求

ALTER PROCEDURE [dbo].[GetOneWeekRosters] 
    -- Add the parameters for the stored procedure here 
    @Date varchar(20), 
    @DepartmentID int, 
    @RosterID int, 
    @RosterWeekID int, 
    @Active bit 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Insert statements for procedure here 
    SELECT distinct n.EmployeeID, n.FirstName, n.Surname, n.DepartmentID, n.InstitutionID, 
    n.ContractedHours, n.ReportingOrder, n.RoleName, 
    ISNULL(RosterLines.Notes, 'no notes') as Notes, ISNULL(RosterLines.ActivityTypeID, 8) as ActivityTypeID, 
    ISNULL(ActivityTypes.ActivityTypeShort, 'NW') as ActivityTypeShort, 
    ISNULL(RosterLines.RosterHourValue,0) as RosterHourValue, 
    ISNULL(RosterLines.RosterLineID, 0) as RosterLineID, ISNULL(RosterLines.PositionID, 1) as PositionID, 
    ISNULL(RosterLines.RosterShiftStart, m.DateDim) as ShiftStart, 
    RosterAreas.RosterAreaName, RosterShifts.RosterShiftName, 
    @RosterWeekID as RosterWeekID, @RosterID as RosterID, 
    ISNULL(RosterLines.RosterShiftFinish, m.DateDim) as ShiftFinish, ISNULL(RosterLines.RosterShiftID, 0) as RosterShiftID, 
    ISNULL(RosterLines.RosterLineID, 0) as RosterLineID, RosterLines.RosterAreaID, 
    m.DateDim as DateEntry from 
    (select DateDimension.DateDim, DateDimension.DayOfWeek_ShortName, DateDimension.Calendar_DayOfMonth 
    from DateDimension where DateDimension.DateDim between Convert(datetime,@Date,103) and (Convert(datetime,@Date,103) + 6)) m 
    cross join 
    (select Employees.EmployeeID, Employees.FirstName, Employees.Surname, Employees.EmploymentTypeID, Employees.ContractedHours, 
    Employees.RoleName, Employees.Active, EmploymentTypes.EmploymentTypeName, EmploymentTypes.ReportingOrder, 
    EmpToDepts.DepartmentID, EmpToDepts.InstitutionID 
    from Employees left join EmploymentTypes on Employees.EmploymentTypeID = EmploymentTypes.EmploymentTypeID 
    left join EmpToDepts on Employees.EmployeeID = EmpToDepts.EmployeeID 
    where EmpToDepts.DepartmentID = @DepartmentID and Employees.Active = @Active) n 
    left join RosterLines on n.EmployeeID = RosterLines.EmployeeID and n.DepartmentID = RosterLines.DepartmentID 
    and m.DateDim = RosterLines.DateEntry left join ActivityTypes on RosterLines.ActivityTypeID = ActivityTypes.ActivityTypeID 
    left join RosterAreas on RosterLines.RosterAreaID = RosterAreas.RosterAreaID 
    left join RosterShifts on RosterLines.RosterShiftID = RosterShifts.RosterShiftID 
    order by n.DepartmentID, n.ReportingOrder, n.Surname, n.FirstName 
END 
+2

该错误与C#代码无关。如果你用相同的参数测试存储过程,它会给你那个错误。存储过程中的某个位置有一个依赖于单个值的条件,但是会返回多个单个值,以便引发错误。要么修复存储的proc,要么编辑问题,只将存储的proc与错误一起存储。就目前而言,没有人可以告诉你错误在哪里,因为我们看不到存储的proc。 – CodingYoshi

+0

您是否尝试过使用EF6查询日志记录或SQL Server分析器,以便查看实际发送到SQL Server的内容? –

+1

你的EF代码是好的,存在的存储过程位于下面,通过提供多个结果集而不是只有一个导致了错误。尝试在SSMS中运行'GetOneWeekRosters'过程,使用调试给定的参数并查看它是否产生多个单独的结果集。 –

回答

1

这不是太多的答案,但我得到的数据集,通过使用ADO.NET,而不是获取存储过程返回。 SPROC确实有效,所以我相信真正的答案是这种方式的一些问题.net核心1.1使用linq返回它的数据集,并可能以它评估存储过程结果的方式返回它的数据集。我没有时间来证明这一点,但目前我有数据和它的好处。通过使用SqlConnection,SqlDataReader和SqlCommand,只需另外50行代码即可手动生成该集合。我创建了一个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; 

    } 

前进。

1

有同样的问题,我注意到我使用多个列相同的列名称。我检查了你的程序,好像RosterLineID被复制,这在某种程度上混淆了EF。无论何时出现此错误,始终检查列名称。希望这有助于...

相关问题