Code sending double value, EF creating query with it the wrong way - c#

I'm filling up an object that has a double. In the database this field is a float. My EF savechanges fails as it says it returns 0 records.
I have used sql profiler to see which query it sends to the database, and this query indeed fails, thus causing it to return 0 records.
So EF is right, but it send my float into a query in a way that makes the query crash. Anyone has any idea why it does this? How I can avoid it?
This is my code object:
public partial class Rate : IRate
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column(Order = 0)]
public int Id { get; set; }
[StringLength(3)]
public string source_currency { get; set; }
[StringLength(3)]
public string target_currency { get; set; }
public DateTime? date_l { get; set; }
public double? rate_exchange { get; set; }
[Key]
[Column(Order = 1)]
public DateTime CreatedOn { get; set; }
}
I put the double value into the rate_Exchange field in c# which works perfectly. Upon inspecting the element using debugger it has the correct double value in there.
However EF sends it to the database formatted like this:
exec sp_executesql N'INSERT [dbo].[Rates]([CreatedOn], [source_currency], [target_currency], [date_l], [rate_exchange])
VALUES (#0, #1, #2, #3, #4)
SELECT [Id]
FROM [dbo].[Rates]
WHERE ##ROWCOUNT > 0 AND [Id] = scope_identity() AND [CreatedOn] = #0',N'#0 datetime2(7),#1 varchar(3),#2 varchar(3),#3 datetime2(7),#4 float',#0='2023-02-08 15:58:58.0231618',#1='RUB',#2='EUR',#3='2023-02-01 00:00:00',#4=0,0132374518222941
obviously this fails cause it used a , instead of a . for the 4th parameter
any clues anyone?

Related

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

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

I probably have spent 4 hours now and tried
Code First approach and
Database first approach
db.MoveJobs.Add(moveJob);
db.SaveChanges();
When a row is inserted it gives me
Cannot insert the value NULL into column 'id', table 'aspnet-AccountVerification.Web3.dbo.MoveJobs'; column does not allow nulls. INSERT fails.
The statement has been terminated.
public class MoveJob
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; }
public string PhoneNumber { get; set; }
}
Basically I need to generate incrementally a key for every itself for a new row. No Stack overflow / Forums / or something has helped.
I strangely worked yesterday though. I cant get where i went wrong
You don't need use [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
The property id by default is key and identity. First remove this attribute and drop your database, after do this add a new migration.

Cannot insert the value NULL into column 'Id', table '; column does not allow nulls

I'm seeing a strange behavior from Entity Framework. I'm using code-first approach to define a One-To-Many relationship between two entities:
public class IncomingCheck : AuditedEntityBase
{
[Key]
public int Id { get; set; }
[Required]
public virtual CheckType Type { get; set; }
[Required]
public virtual Bank Bank { get; set; }
public string Branch { get; set; }
public virtual IList<IncomingCheckHistory> History { get; set; }
}
public class IncomingCheckHistory
{
[Key]
public int Id { get; set; }
public string LongDescription { get; set; }
}
And here's I I'm trying to add an item to the History:
using (var db = new CheckDataContext())
{
foreach (var check in SelectedItems)
{
var dbCheck = await db.IncomingChecks.FindAsync(check.Id);
var history = new IncomingCheckHistory()
{
LongDescription = "something",
};
dbCheck.History.Add(history);
await db.SaveChangesAsync(); //throws the exception
}
}
But it throws an exception saying that "Cannot insert the value NULL into column 'Id'". However I've always done it like this. The database is supposed to fill the Id column itself with a unique number.
What am I missing?
Update:
Using SSProfiler, I got the query that runs on the database. It's as follows:
exec sp_executesql N'INSERT [dbo].[IncomingCheckHistories]([LongDescription], [IncomingCheck_Id])
VALUES (#0, #1)
SELECT [Id]
FROM [dbo].[IncomingCheckHistories]
WHERE ##ROWCOUNT > 0 AND [Id] = scope_identity()',N'#0 nvarchar(max) ,#1 int',#0=N'Something',#1=1
Note that scope_identity() should be getting the Id itself, correct?
Shouldn't the Id be set as the Identity?
Like this:
public class IncomingCheckHistory
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key]
public string LongDescription { get; set; }
}
Hope that this is the solution to your problem!
Well for some strange reason the exact code worked after completely deleting the database and migrations and starting from scratch. I'm not sure why it wouldn't work without migrations. Also I had tried deleting the database before but at the time I was trying a little different code.
In any case the posted code/query should work. Also I checked the database and the columns to see if anything is different and it wasn't. I would appreciate if someone could shed some light on why it wasn't working and it is now.

IQueryable fills null values with other values

Here is what I want to do : Get a List of Batch Objects in my controller that I can send to the view and display it. It's working but the values are mixed up. If the value in the database is null or 0, the query fills it with another non-null value in the record. Here's an example.
Database Content
Id:13
TotalRequest : 10
TotalProcessed :0
CreatedDateTime:2017-01-13 13:30:46.090
CreatedBy:Test
CompletionDateTime : NULL
Iqueryable at position 13 content
Id:13
TotalRequest : 10
TotalProcessed :10
CreatedDateTime:2017-01-13 13:30:46.090
CreatedBy:Test
CompletionDateTime : NULL
You can see that the TotalProcessed is not correct. Also if I have a CompletionDateTime that is not null in one of the objects, the List doesn't care and always outputs null
The code:
IQueryable<Batch> IBatchList = context.batch.OrderByDescending(b => b.CreatedDateTime);
var batchList = IBatchList.ToList();
Batch Class(code first DB, so it's the definition of the DB as well)
public class Batch
{
[Key]
public Int64 Id { get; set; }
public int TotalRequested { get; set; }
public int TotalProcessed { get; set; }
public DateTime CreatedDateTime { get; set; }
public string CreatedBy { get; set; }
public DateTime? CompletedDateTime { get; set; }
}
Id TotalRequested TotalProcessed CreatedDateTime CreatedBy CompletedDateTime
13 10 0 2017-01-13 13:30:46.090 Test NULL
Here's the query from the Iqueryable :
{SELECT
[Extent1].[Id] AS [Id],
[Extent1].[TotalRequested] AS [TotalRequested],
[Extent1].[TotalProcessed] AS [TotalProcessed],
[Extent1].[CreatedDateTime] AS [CreatedDateTime],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent1].[CompletedDateTime] AS [CompletedDateTime]
FROM [dbo].[Batch] AS [Extent1]
ORDER BY [Extent1].[CreatedDateTime] DESC}
I solved the problem, I don't know why it repairs it, but I added a where statement to the query(CreatedDateTime is never null by the way, so I'll alway return all my records) and now I have all the correct data.
IEnumerable<BatchCode> IBatchCodeList = identityContext.BatchCodes.OrderByDescending(bc => bc.CreatedDateTime).Where(bc=>bc.CreatedDateTime != null);

Db.SaveChanges Not Assigning Primary Key ID After Insert - Code First Entity Framework

I have a really weird situation with one class specifically. Upon adding the class to the DbContext to insert into the database and calling Db.SaveChanges code first/ef is not assigning the primary key id back to the class.
It's really odd, I've never encountered this before and I can't seem to find any solutions online.
Here is what the code looks like currently...
Invoice Code First Class
[Table("invoice")]
public class Invoice
{
[Key]
[Column("invoice_id")]
public int InvoiceId { get; set; }
[Column("invoice_credit_card_payment_id")]
public int InvoiceCreditCardPaymentId { get; set; }
[Column("batch_id")]
public int BatchId { get; set; }
[Column("customer_id")]
public int CustomerId { get; set; }
etc.....
}
Code to Insert Invoice into Database
var invoice = new Invoice()
{
BatchId = 0,
Memo = "",
PayDateTime = DateTime.Now,
QuickbooksAccountName = "",
QuickbooksId = "",
Terms = "",
etc....
};
DbContext.Current.Invoices.Add(invoice);
//Invoice record does insert successfully!
DbContext.Current.SaveChanges();
//This returns ZERO
var id = invoice.InvoiceId;
Additional Notes
As a side note the invoice record is successfully inserted into the database, however, the ID is not assigned back to the invoice object.
Another note - I have around 30 other code first classes that work just fine when doing inserts and getting ID's - it's just this one that is giving me issues for some weird reason.
Per jwatts1980 Recommendation
I updated the invoice class to reflect this
[Key]
[Column("invoice_id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int InvoiceId { get; set; }
This did not solve the problem immediately, however it did reveal a new error upon insert:
A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'invoice_id'
I found a stackoverflow answer here which lead me to find some foreign key attributes I had setup on the invoice class:
[ForeignKey("InvoiceId")]
public ICollection<InvoiceOrder> InvoiceOrders { get; set; }
[ForeignKey("InvoiceId")]
public InvoiceCreditCardPayment InvoiceCreditCardPayment { get; set; }
Removing the ForeignKey attributes above seemed to solve the problem so far. I can't say that the it won't cause an other errors, however so far everything appears to be working well.
This attribute might help
[Key]
[Column("invoice_id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int InvoiceId { get; set; }

Categories

Resources