我在使用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 });
答案 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会抛出此异常。