SQL store procedure executes in SQL but not in code - c#

I need your help. I have a store procedure that executes perfectly in SQL but when I call her from an IActionResult from a .net controller with FromSqlRaw(), returns the following error :
System.InvalidOperationException: 'The required column 'SeasonGroupClientCode' was not present in the results of a 'FromSql' operation.'
in Action:
var sql = "EXECUTE sp_seasonDataGroupedHorizonatlallyByCompany";
var list = _context.SeasonGroupedByCompanies.FromSqlRaw(sql).AsNoTracking().ToList();
Store Procedure:
select * from
(SELECT [SeasonGroupSeasonDescription] AS FirstSeason,[SeasonGroupClientCode] AS
FirstSeasonClientCode,[SeasonGroupClientName] AS
FistSeasonClientName,SeasonGroupCompanyId],
SUM([SeasonGroupStartValue]) AS FiSTotalStartValue ,
SUM([SeasonGroupFinalValue]) AS FiSTotalFinalValue
FROM [dbo].[SeasonGroupedByCompanies]
WHERE [SeasonGroupSeasonDescription]='SS21'
GROUP BY [SeasonGroupClientCode],[SeasonGroupClientName],
[SeasonGroupSeasonDescription],[SeasonGroupCompanyId]) as td
full join
(SELECT [SeasonGroupSeasonDescription] AS SecondSeason,[SeasonGroupClientCode] AS
SecondSeasonClientCode,[SeasonGroupClientName] AS SecondSeasonClientName,
[SeasonGroupCompanyId] AS SecondId,
SUM([SeasonGroupStartValue]) AS SeSTotalStartValue ,
SUM([SeasonGroupFinalValue]) AS SeSTotalFinalValue
FROM [dbo].[SeasonGroupedByCompanies]
WHERE [SeasonGroupSeasonDescription]='FW21'
GROUP BY [SeasonGroupClientCode],[SeasonGroupClientName],[SeasonGroupSeasonDescription],
[SeasonGroupCompanyId]) as tf
on td.FistSeasonClientName = tf.SecondSeasonClientName
full join
(SELECT [SeasonGroupSeasonDescription] AS ThirdSeason,[SeasonGroupClientCode] AS
ThirdSeasonClientCode,[SeasonGroupClientName] AS ThirdSeasonClientName,
[SeasonGroupCompanyId] AS ThirdId,
SUM([SeasonGroupStartValue]) AS ThSTotalStartValue ,
SUM([SeasonGroupFinalValue]) AS ThSTotalFinalValue
FROM [dbo].[SeasonGroupedByCompanies]
WHERE [SeasonGroupSeasonDescription]='SS22'
GROUP BY [SeasonGroupClientCode],[SeasonGroupClientName],[SeasonGroupSeasonDescription],
[SeasonGroupCompanyId]) as ts
on td.FistSeasonClientName = ts.ThirdSeasonClientName
full join
(SELECT [SeasonGroupSeasonDescription] AS FourthSeason,[SeasonGroupClientCode]AS
FourthSeasonClientCode,[SeasonGroupClientName] AS FourthSeasonClientName,
[SeasonGroupCompanyId] AS FourthId,
SUM([SeasonGroupStartValue]) AS FoSTotalStartValue ,
SUM([SeasonGroupFinalValue]) AS FoSTtotalFinalValue
FROM [dbo].[SeasonGroupedByCompanies]
WHERE [SeasonGroupSeasonDescription]='FW22'
GROUP BY [SeasonGroupClientCode],[SeasonGroupClientName],[SeasonGroupSeasonDescription],
[SeasonGroupCompanyId]) as tx
on td.FistSeasonClientName = tx.FourthSeasonClientName
Entity
public class SeasonGroupByCompany
{
[Key]
public int SeasonGroupCompanyId { get; set; }
public string? SeasonGroupSeasonDescription { get; set; }
public string? SeasonGroupSalesman { get; set; }
public int SeasonGroupClientCode { get; set; }
public string? SeasonGroupClientName { get; set; }
public int SeasonGroupQuantity { get; set; }
public int SeasonGroupDiscount { get; set; }
public double SeasonGroupStartValue { get; set; }
public double SeasonGroupFinalValue { get; set; }
The same error comes up, even if I run the query directly from FromRawSql().
Thanks in advance, any help will be appreciated

It looks like in the SeasonGroupedByCompany entity you have a field named SeasonGroupClientCode, but in the SQL query you have renamed it into FirstSeasonClientCode:
...[SeasonGroupClientCode] AS FirstSeasonClientCode...
Either rename the field in the entity, or don't rename the column in SQL, because originally the naming looks to be consistent.

Related

EF Core recursive folder structure serialized incorrectly

I'm trying to utilize EF Core to execute a Raw Sql statement and "serialize" it back to a recursive object structure.
My data looks like this
Folders -
Requests -
//Folder.cs
[Table("PsRequestFolder")]
public class PsRequestFolder : IWorkSpaceNode
{
[Key]
public int FolderId { get; set; }
public string FolderName = "";
public PsWorkSpace? FolderWorkSpace { get; set; }
public PsRequestFolder? ParentFolder { get; set; }
public List<PsHttpRequest> Requests { get; set; } = new List<PsHttpRequest>();
public List<PsRequestFolder> Folders { get; set; } = new List<PsRequestFolder>();
...
// Request.cs
[Table("PsHttpRequest")]
public class PsHttpRequest : IWorkSpaceNode
{
[Key]
public int RequestId { get; set; }
public string Url = "";
public string RequestName = "";
public PsWorkSpace RequestWorkSpace{ get; set; }
public int PsRequestFolderFolderId { get; set; }
public PsRequestFolder ContainingFolder { get; set; }
...
I'm executing this sql statement by calling FromSqlRaw
ws.RequestFolders = await context.RequestFolders.FromSqlRaw(
#"
WITH cte_ws AS (
SELECT
FolderId,
FolderName,
ParentFolderFolderId,
FolderWorkSpaceWorkSpaceId,
p1.*
FROM PsRequestFolder
LEFT JOIN PsHttpRequest AS p1 ON PsRequestFolder.FolderId = p1.PsRequestFolderFolderId
WHERE ParentFolderFolderId IS NULL
UNION ALL
SELECT
e.FolderId,
e.FolderName,
e.ParentFolderFolderId,
e.FolderWorkSpaceWorkSpaceId,
p1.*
FROM PsRequestFolder as e
LEFT JOIN PsHttpRequest AS p1 ON e.FolderId = p1.PsRequestFolderFolderId
INNER JOIN cte_ws o
on o.FolderId= e.ParentFolderFolderId
)
SELECT * FROM cte_ws;
"
).ToListAsync();
I would expect to get back something that looks like
One
RequestOne
RequestTwo
Two
Six
Eight
Nine
RequestThree
Seven
Three
Four
Five
Instead I get something like this back
Not sure why some of the things that should be nested underneath others aren't being nested as well as why the requests under folder Nine don't come through at all, as well folder Nine and some others being written twice to the list
The raw sql output just running it against the db is -
Any assistance is greatly appreciated!

Using a stored procedure to retrieve all or single user from AspNetUsers table

I see a lot of information on ASP.Net Core Identity storing DATA with the stored procedure and I tried and use the same method to retrieve / Get all or a single user detail from AspNetUsers table in SQL, but did not succeed.
below is my code.
My Stored Procedure
alter PROCEDURE [dbo].[spEmployeeDetails]
#EmployeeID varchar(50) = ''
AS
BEGIN
IF(#EmployeeID !='')
BEGIN
SELECT * FROM AspNetUsers WHERE EmployeeId like #EmployeeID + '%'
END
ELSE
BEGIN
SELECT * FROM AspNetUsers
END
END
Model class
public class AppUsers:IdentityUser
{
public string EmployeeId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Nationality { get; set; }
public string PositionTitle { get; set; }
public string Department { get; set; }
public string DepartmentCode { get; set; }
public string PosCode { get; set; }
public string Grade { get; set; }
}
service class
public AppUsers GetaUser(string id)
{
var getuser = context.AppUsers.FromSqlRaw($"spEmployeeDetails {id}").ToList();
return getuser.FirstOrDefault();
}
the error I am getting is
InvalidOperationException: 'FromSqlRaw' or 'FromSqlInterpolated' was called with non-composable SQL and with a query composing over it. Consider calling 'AsEnumerable' after the method to perform the composition on the client side.
I tried this code also but no luck
IEnumerable<AppraisalUsers> objd = context.AppraisalUsers.FromSqlRaw($"spEmployeeDetails {id}").AsEnumerable<AppraisalUsers>();
can anyone help me to retrieve a user from AspNetUsers table generated by Identity framework
I am working on Core3.1
Instead of FromSqlRaw you should use FromSqlInterPolated to stop sql injection attacks.
You can try adding the SQL Parameter name like so
context.AppUsers.FromSqlInterPolated ($"exec spEmployeeDetails #EmployeeID={id}")
You could also write this as pure ef core code as
return context.AppUsers.FirstOrDefault(e => e.EmployeeId == id);

How can i use SQL inner join statement as query in LINQ

SELECT
Id,
No,
NetAmount,
PaidAmount,
NetAmount - PaidAmount AS AmountToBePayed
FROM
(
SELECT
m.Id,
m.No,
SUM(NetAmount) as NetAmount,
(
SELECT
COALESCE( SUM( PaidAmount ), 0 )
FROM
A_Account_Payable_Payment_Invoice
) as PaidAmount
FROM
A_Account_Payable_Invoice_M m
INNER JOIN A_Account_Payable_Invoice_Item d ON
m.Id = d.A_Account_Payable_Invoice
GROUP BY
m.Id,
m.No
) a
How can i use this query directly in LINQ C#
As you mentioned on comment section you don't want to translate SQL to LINQ, you just want to directly run this script.
To do so first you need to create class that will match with your Script like:
[DataContract()]
public class PaymentInvoiceResult
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int No { get; set; }
[DataMember]
public int NetAmount { get; set; }
[DataMember]
public int PaidAmount { get; set; }
[DataMember]
public int AmountToBePayed { get; set; }
}
Then you need to use SqlQuery as following:
List<PaymentInvoiceResult> paymentInvoiceResultList = db.Database.SqlQuery<PaymentInvoiceResult>("Your Script").ToList();
You can simply use:
var results = db.ExecuteQuery(typeof(DTO), "sql query ");
Your dto should have members:
Id,
No,
NetAmount,
PaidAmount,
NetAmount - PaidAmount AS AmountToBePayed

Dapper with postgresql error (sequence contains more than one element)

I am getting this error when I run an integration test against my Postgresql DB using a stored procedure.
Result Message: System.InvalidOperationException : Sequence contains more than one element
Here is the repo file:
public card_view SelectView(int card_id)
{
using (var connection = new NpgsqlConnection(ConfigurationSettings.GetConnectionString()))
{
var p = new DynamicParameters();
p.Add("#card_id", card_id);
using (var multi = connection.QueryMultiple("f_card_select_view", p, commandType: CommandType.StoredProcedure))
{
card_view view = multi.Read<card_view>().Single();
view.Categories = multi.Read<category>().ToList();
view.Modifiers = multi.Read<card_modifier_view>().ToList();
return view;
}
}
}
The card test file:
[Test]
public void SelectViewTest()
{
var repo = new CardRepository();
var result = repo.SelectView(31); // witch
Assert.AreEqual(2, result.Categories.Count);
Assert.AreEqual(2, result.Modifiers.Count);
}
Cardview file:
public class card_view
{
public int card_id { get; set; }
public int cardset_id { get; set; }
public string cardset_title { get; set; }
public string image_path { get; set; }
public string cardset_name { get; set; }
public int card_cost { get; set; }
public List<card_modifier_view> Modifiers { get; set; }
public List<category> Categories { get; set; }
}
cardmodifierview file:
public class card_modifier_view
{
public int card_modifier_id { get; set; }
public int card_id { get; set; }
public int modifier_type_id { get; set; }
public int? modifier_value { get; set; }
public string instruction_text { get; set; }
public string modifier_type_name { get; set; }
}
The DB function (The original SQL was T-SQL and I have done my best to translate it into regular SQL for postgres.)
CREATE FUNCTION f_card_select_view (card_id int)
RETURNS TABLE(card_id bigint, modifier_type_id integer,
instruction_text integer, modifier_type_name integer, card_modifier character varying, modifier_type character varying)
AS $$
SELECT card_id,cardset.cardset_id,card_title,image_path,card_cost,cardset_name
FROM card
INNER JOIN cardset ON card.cardset_id = cardset.cardset_id
WHERE card_id = #card_id;
SELECT card.category_id,category_name
FROM category card
INNER JOIN card_category ON card.category_id = card_category.category_id
WHERE card_category.card_id = #card_id;
SELECT f_card_modifier_selectby_card_id (#card_id);
$$ LANGUAGE sql;
Here is f_card_modifier_selectby_card_id:
CREATE FUNCTION f_card_modifier_selectby_card_id(card_id int)
RETURNS TABLE(
card_id bigint,
modifier_type_id int,
instruction_text int,
modifier_type_name int,
card_modifier varchar,
modifier_type varchar
)
AS $$
SELECT
card_modifier_id,
card_id,
card_modifier.modifier_type_id,
modifier_value,
instruction_text,
modifier_type_name
FROM card_modifier INNER JOIN modifier_type ON card_modifier.modifier_type_id = modifier_type.modifier_type_id
WHERE card_id = card_id
$$ LANGUAGE sql;
If the error is Sequence contains more than one element, then the problem is that your first query (where you have the .Single()) is returning more than one row. I can't tell you why that is, but you need to try running:
SELECT card_id,cardset.cardset_id,card_title,image_path,card_cost,cardset_name
FROM card
INNER JOIN cardset ON card.cardset_id = cardset.cardset_id
WHERE card_id = #card_id;
(with your expected #card_id) in your SQL toolkit to see what happens. Or better: call the stored procedure itself - presumably via:
EXEC f_card_select_view {your id here}
It looks like your statement brings back a join containing multiple records for card_view or 0.
In other frameworks certainly you can use SingleOrDefault() to allow for 0 records. Note this will still error for multiple records.
If its getting multiple records you need to establish if this is correct and rework it to be a collection like you have done with .ToList() or correct your data in the database and possibly your keys.

Return custom table from Stored Procedure In Ef Code First

Is it possible to return custom table from SP . I'm using EF code first approach.
This is my SP
CREATE PROCEDURE [dbo].[GetUserNotification]
#ToUserId INT
AS
BEGIN
select TU.FullName as ToUserName,
FU.FullName as FromUserName,
N.NotificationClickType,
N.TemplateId,
J.Title as JobTitle,
J.Identifier as JobIdentifier,
B.Identifier as BidIdentifier
from Notification N
inner Join AppUser TU on TU.Identifier = N.ToUserId
inner Join AppUser FU on FU.Identifier = N.FromuserId
inner Join Bid B on B.Identifier = N.NotificationBidId
inner Join Job J on J.Identifier = B.JobId
where N.ToUserId=#ToUserId
Order By N.Identifier DESC
END
my Custom View Model
public class NotificationModel
{
public string ToUserName { get; set; }
public string FromUserName { get; set; }
public NotificationClickType NotificationClickType { get; set; }
public int TemplateId { get; set; }
public string JobTitle { get; set; }
public int JobIdentifier { get; set; }
public int BidIdentifier { get; set; }
}
I have created same ViewModel. But every where I have seen Using SP i can return Only single table data which I have added in my DbContext class.
When you add your stored procedure to the EF Model, it will automatically create a complex type. (At least it did for me, using Model First).
The name of the complex type is the SP name with “_Result” added, e.g. GetUserNotification_Result.
You can use the complex type like:
using (Entities dbContext = new Entities())
{
List<GetUserNotification_Result > data = dbContext.GetUserNotification(userId).ToList();
}
Alternatively, https://msdn.microsoft.com/en-us/data/jj691402.aspx shows how to use Code first. How to call Stored Procedure in Entity Framework 6 (Code-First)? may also be helpful.

Categories

Resources