简体   繁体   中英

Filter results from Stored Procedure using Linq

I have a query which I cannot do in Linq, as it uses 2 separate databases. Instead, I have written a stored procedure in SQL Server.

Now I need to manipulate the results.

Here is my stored procedure:

ALTER PROCEDURE [dbo].[HealthAndSafety] 
    @EventClass nvarchar(50), 
    @EventDateTime datetime
AS
BEGIN
    SELECT     
       SQLPendingEvent.EventType AS Answer,
       (SELECT Description
        FROM RepairCodes
        WHERE (Code = RepairCodes_1.Code) AND (Type = 'HSQUESTION')
       ) AS HSQuestion, 
       (CASE WHEN RepairCodes_1.Type = 'HSANSWERY' THEN 'Yes' ELSE 'No' END) AS HSAnswer, 
       SQLPendingEvent.EventDateTime AS completionDate,  
       SQLPendingEvent.KeyPropertyID, 
       SVSExtract.dbo.Property.Address1 + '  ' + SVSExtract.dbo.Property.Address2 + '  ' + SVSExtract.dbo.Property.Postcode AS Address, 
       SQLPendingEvent.KeyEntityID AS JobNumber, SQLPendingEvent.KeyUserID
   FROM         
      SQLPendingEvent 
   INNER JOIN
      RepairCodes AS RepairCodes_1 ON SQLPendingEvent.EventType = RepairCodes_1.Description 
   LEFT OUTER JOIN
      SVSExtract.dbo.Property ON SQLPendingEvent.KeyPropertyID = SVSExtract.dbo.Property.KeyProperty
   WHERE     
      (SQLPendingEvent.EventClass = @EventClass) 
      AND (SQLPendingEvent.EventCode = 'EVENT') 
      AND (SQLPendingEvent.EventDateTime > @EventDateTime)
   ORDER BY 
      SQLPendingEvent.KeyUserID

And here is my C# code:

var eventTable = OnSiteV3.HealthAndSafety(_EventClass, _EventDateTime);

First I want to extract from this result a list of distinct UserIDs.

Then I want to filter those results on a column called UserID .

Something like this:

var userList = eventTable.AsEnumerable().Select(row => new
        {
            KeyUserID = (string)row.KeyUserID
        }).Distinct();

And this:

eventTable = eventTable.Where(r => r.KeyUserID == selectedUser);

Both these examples here come from a different kind of query, like below, but how do I do it with my stored procedure?

var eventTable = (from s in OnSiteV3.SQLPendingEvents
                  join r in OnSiteV3.RepairCodes on s.EventType equals r.KeyRepairCode
                  select new
                          {
                              s.KeyDeviceID,
                              s.UpdateTime,
                              s.EventType,
                              s.EventDateTime,
                              s.EventText,
                              s.KeyUserID,
                              s.EventCode,
                              r.Type
                          }).Where(s => s.EventCode == _eventCode && s.Type == _repairType && s.EventDateTime > _EventDateTime).Distinct();

Finally got it working. here is my final code:

    OnSiteV3DataContext OnSiteV3 = new OnSiteV3DataContext();

            var eventTable = OnSiteV3.HealthAndSafety(_EventClass, _EventDateTime).ToList();

            if (selectedUser != string.Empty)
            {
                var eventTableFiltered = eventTable.Where(o => o.KeyUserID == selectedUser).ToList();
                gvHealthAndSafety.DataSource = eventTableFiltered;
                gvHealthAndSafety.DataBind();
            }
            else
            {
                gvHealthAndSafety.DataSource = eventTable;
                gvHealthAndSafety.DataBind();
            }

            var userList = eventTable.Select(row => new { KeyUserID = (string)row.KeyUserID }).Distinct();

            ddlUsers.DataSource = userList;
            ddlUsers.DataTextField = "KeyUserID";
            ddlUsers.DataValueField = "KeyUserID";
            ddlUsers.DataBind();

I think that you can do it in the same way using the Property ReturnValue of the stored procedure.

Call the stored procedure like this

[Function(Name="dbo.Call me as you want")]
public ISingleResult<YourTableResult> GetSomething([Parameter(DbType="NVarChar(20)")] string param1)
{
    IExecuteResult result = this.ExecuteMethodCall(this,         ((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);
    return ((ISingleResult<YourTableResult>)(result.ReturnValue));
}

then tou can use it in others functions in this way

ISingleResult<YourTableResult> result =
        db.GetSomething("ParameterValue");

//now you can use the code that you already use like this

    var userList = result.AsEnumerable().Select(row => new
            {
                KeyUserID = (string)row.KeyUserID
            }).Distinct();

refer here for documentation

eventTable is an ISingleResult<T> , which is an interface that extends IEnumerable<T> to additionally capture the return value of the stored procedure call.

Where<T> accepts an IEnumerable<T> (which eventTable is), but returns an IEnumerable<T> . Since you can't implicitly downcast from an IEnumerable<T> to an ISingleResult<> ,you can't store the result of where back in eventTable , and the compiler throws an error.

You have some options:

  • make eventList an IEnumerable<HealthAndSafetyResult> , either explicitly or using AsEnumerable() :

     var eventTable = OnSiteV3.HealthAndSafety(_EventClass, _EventDateTime) .AsEnumerable(); 
  • store the result of Where in a differently-typed variable:

     var eventTableFiltered = eventTable.Where(r => r.KeyUserID == selectedUser); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM