2017-07-28 65 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。無論何時出現此錯誤,始終檢查列名稱。希望這有助於...

相關問題