Entity Framework Core 6 - System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values - entity-framework-core

I'm using EF Core 6 on .NET 6.0 and am looking at this error:
System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values
The error message should indicate that EF Core is trying to read a value for a required property, i.e. a property which should never have null value in the database, but instead the underlying data reader reports null value for that property in some record(s).
Entity Framework Core: `SqlNullValueException: Data is Null.` How to troubleshoot?
Disabling nullable reference type the error disappears and everything works well.
Is it possible to investigate exactly what field is causing this issue, debugging the code doesn't give me more details.
Is there some technique to get the name of the offending field or fields?
Visually I didn't find any discrepancy between the database and the model

Check the document related with Nullable reference types
In a nullable aware context:
A variable of a reference type T must be initialized with non-null,
and may never be assigned a value that may be null.
A variable of areference type T? may be initialized with null or
assigned null, but is required to be checked against null before
de-referencing.
assuming an entity:
public class SomeEntity   
{   
[Key]     
public int Id { get; set; }       
  public string Name { get; set; }        
public string Prop { get; set; }    
}
If you enabled nullable reference type, Name and Prop property would never be assigned with null
Assuming the Db:
When you read data from db and assign the null value in db to your entity,you would get the error you've shown
Is it possible to investigate exactly what field is causing this issue
All properties type of T instead of T? in your entity with the column could be null in db would cause this issue
Both Disabling nullable reference type and Setting your property which may have null value in db with T? would solve the issue.
For example,in my case,the Name column and Prop column could be null in db,when you check your entity, Name and Prop property should be type of string? instead of string .

yes, this is the cause.
But my question (maybe is not so clear, it's my falut) is about how to get some sort of notification from the debbugger, the call stack, or from a verbose output, an indicatin of what field has null value
It's not so easy to verify manually because my entity are a customization of a the aspnet identity database
E.G: calling _userManager.FindByNameAsync i got this error
Apparently i've filled all nullable values but maybe the error is caused by other related entity e.g Roles, Claims, and so on
So i'd like to get a clear indication about what is the first field(if there are more) that has caused the problem.
If possible of course!

Related

Entity framework 6 - Access the entity object during valueConverter

I have a project with Entity Framework Core 6 for SQL. it's a large project with a lot of entities and properties (and yes, a lot...). All properties are defined not nullable (bool, int etc.) because the SQL database tables all are not-nullable columns also. All good.
But now this project must works with an Oracle database server, and here are tables with nullable columns which not match with the not nullable entities (Oracle EF cannot match nullabe column with a not-nullable directly).
Changing all columns with not nullable with default value isn't possible. And making the entities nullable give us a lot of (test) work because it hits the logical part of code.
So, my challenge is to find a solution that nullable table columns can set not-nullable entity properties with a value or default and without changing the entity set of code.
Using the ValueConverter is the first solution but it isn't possible because a null value will never be passed to a value converter.
So I try it with a shadow property. I have this:
entityTypeBuilder.Ignore(property.Name);
entityTypeBuilder.Property<int?>($"_Nullable_{property.Name}")
.HasConversion<NullableIntConverter >()
.HasColumnName(oracleColumn.ColumName);
Here I ignore the original property for EF, then I add a shadow property with converter for the nullable type (<int?>). This is the valueConverter:
internal class NullableIntConverter : ValueConverter<int, int?>
{
public NullableIntConverter()
: base(
_convertToEntityProviderExpression,
_convertToDbProviderExpression)
{
}
private static readonly Expression<Func<int?, int>> _convertToDbProviderExpression = x =>
x.GetValueOrDefault();
private static readonly Expression<Func<int, int?>> _convertToEntityProviderExpression = x => x;
}
This works, a nullable column set the shadow property but not the original property.
The solution will be setting the original property during ValueConverter. But because of static it isn't really possible. Or maybe someone have a solution here? If I have the entity object, I can use reflection for setting the original property.
I hope that someone have a tip for a solution?

Entity Framework 7 Fluent API Doesn't Recognize IsOptional()

I'm currently setting up my database in my Asp.Net 5 project using entity framework 7, previously with EF 6, when I wanted to make some of my columns nullable, I would use:
modelBuilder.Entity<Article>().Property(t => t.ArticleDateModified).IsOptional();
But it seems that IsOptional is not part of EF7 anymore, I was wondering how can I achieve the same thing using EF7?
Edit:
Marc's answer is indeed correct, first I though it worked because I found something that was like IsOptional:
builder.Entity<Article>().Property(t => t.ArticleDateModified).IsRequired(false);
But after I ran some test without it, it set the database column nullable because I marked it as nullable in my domain model:
public DateTime? ArticleDateModified { get; set; }
Also worth to note that when I made the DateTime non-nullable and used the IsRequired(false), I got the following error:
The property 'ArticleDateModified' on entity type 'Article' cannot be marked as nullable/optional because the type of the property is 'DateTime' which is not a nullable type. Any property can be marked as non-nullable/required, but only properties of nullable types and which are not part of primary key can be marked as nullable/optional.
so, I wonder what is the use of IsRequired(false) here if all I have to do to make a database column nullable is to make it nullable in my domain class?
Based on the note in this documentation page, it would appear that support for doing this declaratively was rescinded. To wit:
A property whose CLR type cannot contain null cannot be configured as optional. The property will always be considered required by Entity Framework.
That this was intentional can be seen in the design discussions from the project hosting on GitHub, specifically:
That is, a property marked as nullable supports null values, while a property marked as non-nullable must never contain null values. It follows from this that marking a property which is of a non-nullable CLR type as allowing nulls will not be allowed. This is different from the EF6 behavior where this is allowed. [emphasis added]
The upshot is, in EF7 a NULL column strictly implies a nullable mapped property. If your property is nullable, the associated column must be NULL unless you mark or configure it with IsRequired.
Response to OP edits
That's interesting, I didn't initially see the documentation on an IsRequired(bool) API. I found a discussion point on it in some June meeting notes that state that this would be the equivalent of EF6's IsOptional():
.IsOptional() - We'll provide this functionality via calling Required(false)
.IsRequired() - Provide Required() with the same functionality
Even though this was the original intent, the design decision to rescind support dates from October. (Per update) attempting to set IsRequired(false) on a non-nullable property results in a run-time error, rather than having been removed entirely.
Though now superfluous, the API cannot be removed without breaking valid code: it wasn't implemented with separate IsRequired(bool) and IsRequired() definitions, but with a single IsRequired(bool required = true). If it were removed and replaced with the parameterless version it would be a breaking change.
Em... Declare Property as nullable?
class Article
{
public DateTime? ArticleDateModified {get;set;}
}
There is not IsOptional in EntityFrameworkCore but there is IsRequired to do the oposite. By default field are nullable if the C# type is nullable.
And more over you cannot set the foreign key which is the primary key of another table using the IsRequire(false) method. if you do so EntityframeworkCore throw an error.
public class User
{
public int Id {get; set;}
public string Username {get;set}
public byte Interest {get;set;}
public Interest Interest {get;set;}
}
public class Interest
{
public byte Id {get;set;}
public string Name {get;set;}
}
ApplicationDbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.property(u => u.InterestId)
.isRequired(false);
}
Error
The property 'InterestId' on entity type 'User' cannot be marked as nullable/optional because the type of the property is 'byte' which is not a nullable type. Any property can be marked as non-nullable/required, but only properties of nullable types and which are not part of primary key can be marked as nullable/optional.
So the best way is to make the property nullable like this.
public byte? InterestId {get; set;}
public Interest Interest {get; set;}

ef4 poco double/float dbtype mapping

I have an exiting database with couple of float/double fields, I chose to use EF4.1 for my DAL/ORM, but I am having problems when reading/saving data to his type of fields. There is no model, just using model builder to configure the entities.
First there was a rounding problem, I think typical of floating point math, so because all of the precision were already set as 2 decimals, I switched to using decimal type on the c# (EF) side, but now when I am trying to get an entity, I get an exception saying I am in trouble.
The 'xxxkg' property on 'YYY' could not be set to a 'Double' value.
You must set this property to a non-null value of type 'Decimal'.
xxxkg is float null on the database, and the value is 10 in the specific case, and in the class it is
public decimal? xxxkg { get; set; }
The question is how to deal with dbtype float/double variables with EF4 (poco)?
You cannot define your property as decimal if it is double in database. EF does not type conversion (and doesn't allow you defining your own) and double value cannot be assigned to decimal variable so populating your class from read record will fail. You must use double.

InvalidOperationException You must set this property to a non-null value of type string

The XX property on 'Table' could not be set to a 'Byte[]' value. You must set this property to a non-null value of type 'String'.
I didn't create the mapping myself, this was generated from a db first scenario. I am not inserting anything to a table, I'm just performing a select, this shouldn't happen at all? Why am I getting this error and how do I fix it?
I had a similar issue but for byte to bool
I edited my entity
public byte XX { get; set; }
Then edited my Model to have
public bool XX { get; set; }
used auto mapper to map them together and it fixed the issue i was having, try this with editing your Model to a string and map it accordingly.
i am using code first for my existing databases, but it may work for db first

How do I get the entity framework to stop setting the rowversion field?

Im using the Entity Framework and I have a rowversion (timestamp) field on a table to use for concurrency. However, when updating the entity object, it keeps trying to set the rowversion column to null, and I get an error:
The 'VerCol' property on 'LmpDemoRequest' could not be set to a 'null' value. You must set this property to a non-null value of type 'Byte[]'.
I have the VerCol column within the entity definition, but I am unable to remove the "Setter" function.
How do I get the entity framework to stop attempting to set this column?
You can pass any arbitrary, valid values for the RowVersion fields (DateTime.Now for example). They will be overwritten with the server-generated values.
For future releases of EF, there should be support for "shadow properties", which exist in the model but not in your classes. That feature would be useful in situations such as this.
I had a case where a view included a RowVersion column from a table that was left joined in the view... so that column could be null sometimes.
But EF4 'knows' that a RowVersion column cannot be null, so even in a simple LINQ query, it was throwing an InvalidOperationException:
The 'PersonRowVersion' property on 'vVoteInfo' could not be set to a 'DBNull' value. You must set this property to a non-null value of type 'Byte[]'
I finally had to change the view to use this for the RowVersion column, so that EF would be happy:
coalesce(p._RowVersion, cast(0 as binary(6))) [PersonRowVersion]