web-dev-qa-db-fra.com

Entity Framework Core: `SqlNullValueException: Data is Null.` Comment dépanner?

J'utilise Entity Framework Core dans une application ASP.NET Core et une action de contrôleur et je n'ai rien changé au code de travail ni à la base de données, mais je ne peux pas dire quelle est la requête effectuée par Entity Framework Core.

L'action du contrôleur:

[HttpGet]
// GET: Administration/Companies
public async Task<ActionResult> Index()
{
    var users = await UserManager.Users.ToListAsync();

    var companyEditVMs = await DB.Companies
    .OrderBy(company => company.CompanyId == 1 
        ? "_" + company.CompanyName 
        : company.CompanyName
    )
    Select(a => new CompanyEditVM(HttpContext, a, users.Where(b => b.CompanyId == a.CompanyId)))
    .ToListAsync();

    return View(companyEditVMs);
}

La trace

SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
System.Data.SqlClient.SqlBuffer.get_String()
System.Data.SqlClient.SqlDataReader.GetString(int i)
lambda_method(Closure , DbDataReader )
Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable<T>+AsyncEnumerator.BufferlessMoveNext(DbContext _, bool buffer, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync<TState, TResult>(TState state, Func<DbContext, TState, CancellationToken, Task<TResult>> operation, Func<DbContext, TState, CancellationToken, Task<ExecutionResult<TResult>>> verifySucceeded, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable<T>+AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider+ExceptionInterceptor<T>+EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
System.Linq.AsyncEnumerable.Aggregate_<TSource, TAccumulate, TResult>(IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken) in Aggregate.cs
KYC.Core.Areas.Commercial.Controllers.CompaniesController.Index() in CompaniesController.cs
-
        [HttpGet]
        // GET: Administration/Companies
        public async Task<ActionResult> Index()
        {
            var users = await UserManager.Users.ToListAsync();

            var companyEditVMs = await DB.Companies
                .OrderBy(company => company.CompanyId == 1 
                    ? "_" + company.CompanyName 
                    : company.CompanyName
                )
                .Select(a => new CompanyEditVM(HttpContext, a, users.Where(b => b.CompanyId == a.CompanyId)))
                .ToListAsync();
lambda_method(Closure , object )
Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable+Awaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()

J'ai même essayé de faire juste var companies = await DB.Companies.ToListAsync(). et j'ai exactement la même exception.

Peut-être que je voudrais pouvoir récupérer la requête effectuée par EF Core pour le faire manuellement afin que je puisse essayer de comprendre ce qui ne va pas avec la requête.

Je me demande ce qui aurait pu arriver. D'autant plus que d'autres entités comme l'utilisateur ou les pays peuvent toujours être récupérées dans la base de données.

Une idée comment puis-je résoudre le problème sous-jacent réel?

[ÉDITER]

Les seules qui ont réellement changé dans le "code" sont les références de nuget, j'ai essentiellement mis à jour à peu près tout, même si cela n'a pas cassé une référence dans le code, il semble que cela change la façon dont EF Core interprète la base de données (supposition sauvage).

J'ai réinitialisé mon référentiel git au point juste avant la mise à jour des paquets nuget et les choses fonctionnent.,. J'ai alors décidé de simplement mettre à jour EntityFrameworkCore de 2.0.2 à 2.2.4 (également essayé avec 2.2.0 et fini avec le même résultat) et le problème se reproduit ... Je ne sais pas ce qui a changé entre 2.0.2 et 2.2. 0 pour déclencher cette exception (mais le modèle est le même juste la version EF Core a changé) ...

Voici la définition de l'entité, elle semble avoir été générée automatiquement avec un outil de la table/schéma de base de données:


    [Table("T_Companies")]
    public partial class Company : INotifyPropertyChanging, INotifyPropertyChanged
    {
        public override string ToString()
        {
            return CompanyId + " " + CompanyName;
        }

        private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(string.Empty);

        private int _CompanyId;

        private string _CompanyName;

        private int _CompanyTypeId;

        private int _CountryId;

        private string _CompanyVatNumber;

        private string _CompanyStreetAddress;

        private string _CompanyZipCode;

        private string _CompanyCity;

        private string _ContactLastName;

        private string _ContactFirstName;

        private bool? _Active;

        private int? _AccountId;

        private string _CallbackSalt;

        private int? _UserSpaceId;

        private string _Login;

        private string _Pwd;

        private bool _IsTechnicalAccount;

        private DateTime? _StatusDate;

        private int _BankStatusCode;

        private string _PivotalAccount;

        private CompanyType _CompanyType;

        private Country _Country;

        private bool _IsKycIdSent;

        #region Extensibility Method Definitions
        partial void OnLoaded();
        partial void OnCreated();
        partial void OnCompanyIdChanging(int value);
        partial void OnCompanyIdChanged();
        partial void OnCompanyNameChanging(string value);
        partial void OnCompanyNameChanged();

        partial void OnCompanyCityChanging(string value);
        partial void OnCompanyCityChanged();
        partial void OnCompanyZipCodeChanging(string value);
        partial void OnCompanyZipCodeChanged();
        partial void OnContactLastNameChanging(string value);
        partial void OnContactLastNameChanged();
        partial void OnActiveChanging(bool? value);
        partial void OnActiveChanged();
        partial void OnCompanyTypeIdChanging(int value);
        partial void OnCompanyTypeIdChanged();
        partial void OnCountryIdChanging(int value);
        partial void OnCountryIdChanged();
        partial void OnContactFirstNameChanging(string value);
        partial void OnContactFirstNameChanged();
        partial void OnCompanyVatNumberChanging(string value);
        partial void OnCompanyVatNumberChanged();
        partial void OnCompanyStreetAddressChanged();
        partial void OnCompanyStreetAddressChanging(string value);
        partial void OnAccountIdChanging(int? value);
        partial void OnAccountIdChanged();
        partial void OnCallbackSaltChanging(string value);
        partial void OnCallbackSaltChanged();
        partial void OnUserSpaceIdChanging(int? value);
        partial void OnUserSpaceIdChanged();
        partial void OnLoginChanging(string value);
        partial void OnLoginChanged();
        partial void OnPwdChanging(string value);
        partial void OnPwdChanged();
        partial void OnIsTechnicalAccountChanging(bool value);
        partial void OnIsTechnicalAccountChanged();
        partial void OnStatusDateChanging(DateTime? value);
        partial void OnStatusDateChanged();
        partial void OnBankStatusCodeChanging(int value);
        partial void OnBankStatusCodeChanged();
        partial void OnPivotalAccountChanging(string value);
        partial void OnPivotalAccountChanged();
        partial void OnIsKycIdSentChanging(bool value);
        partial void OnIsKycIdSentChanged();

        #endregion

        public Company()
        {
            OnCreated();
        }

        [Key, Column("CompanyId"), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int CompanyId
        {
            get => _CompanyId;
            set
            {
                if (_CompanyId != value)
                {
                    OnCompanyIdChanging(value);
                    SendPropertyChanging();
                    _CompanyId = value;
                    SendPropertyChanged("CompanyId");
                    OnCompanyIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("CompanyName"), Required]
        public string CompanyName
        {
            get => _CompanyName;
            set
            {
                if (_CompanyName != value)
                {
                    OnCompanyNameChanging(value);
                    SendPropertyChanging();
                    _CompanyName = value;
                    SendPropertyChanged("CompanyName");
                    OnCompanyNameChanged();
                }
            }
        }

        [Column("CompanyTypeId"), Required]
        public int CompanyTypeId
        {
            get => _CompanyTypeId;
            set
            {
                if (_CompanyTypeId != value)
                {
                    OnCompanyTypeIdChanging(value);
                    SendPropertyChanging();
                    _CompanyTypeId = value;
                    SendPropertyChanged("CompanyTypeId");
                    OnCompanyTypeIdChanged();
                }
            }
        }


        [Column("CountryId"), Required]
        public int CountryId
        {
            get => _CountryId;
            set
            {
                if (CountryId != value)
                {
                    OnCountryIdChanging(value);
                    SendPropertyChanging();
                    _CountryId = value;
                    SendPropertyChanged("CountryId");
                    OnCountryIdChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(100), Column("CompanyCity"), Required]
        public string CompanyCity
        {
            get => _CompanyCity;
            set
            {
                if (_CompanyCity != value)
                {
                    OnCompanyCityChanging(value);
                    SendPropertyChanging();
                    _CompanyCity = value;
                    SendPropertyChanged("CompanyCity");
                    OnCompanyCityChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(100), Column("CompanyStreetAddress"), Required]
        public string CompanyStreetAddress
        {
            get => _CompanyStreetAddress;
            set
            {
                if (_CompanyStreetAddress != value)
                {
                    OnCompanyStreetAddressChanging(value);
                    SendPropertyChanging();
                    _CompanyStreetAddress = value;
                    SendPropertyChanged("CompanyStreetAddress");
                    OnCompanyStreetAddressChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(30), Column("CompanyVatNumber"), Required]
        public string CompanyVatNumber
        {
            get => _CompanyVatNumber;
            set
            {
                if (_CompanyVatNumber != value)
                {
                    OnCompanyVatNumberChanging(value);
                    SendPropertyChanging();
                    _CompanyVatNumber = value;
                    SendPropertyChanged("CompanyVatNumber");
                    OnCompanyVatNumberChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(10), Column("CompanyZipCode"), Required]
        public string CompanyZipCode
        {
            get => _CompanyZipCode;
            set
            {
                if (_CompanyZipCode != value)
                {
                    OnCompanyZipCodeChanging(value);
                    SendPropertyChanging();
                    _CompanyZipCode = value;
                    SendPropertyChanged("CompanyZipCode");
                    OnCompanyZipCodeChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(1024), Column("ContactLastName"), Required]
        public string ContactLastName
        {
            get => _ContactLastName;
            set
            {
                if (_ContactLastName != value)
                {
                    OnContactLastNameChanging(value);
                    SendPropertyChanging();
                    _ContactLastName = value;
                    SendPropertyChanged("ContactLastName");
                    OnContactLastNameChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("ContactFirstName"), Required]
        public string ContactFirstName
        {
            get => _ContactFirstName;
            set
            {
                if (_ContactFirstName != value)
                {
                    OnContactFirstNameChanging(value);
                    SendPropertyChanging();
                    _ContactFirstName = value;
                    SendPropertyChanged("ContactFirstName");
                    OnContactFirstNameChanged();
                }
            }
        }

        [Column("Active"), Required]
        public bool? Active
        {
            get => _Active;
            set
            {
                if (_Active != value)
                {
                    OnActiveChanging(value);
                    SendPropertyChanging();
                    _Active = value;
                    SendPropertyChanged("Active");
                    OnActiveChanged();
                }
            }
        }

        [Column("AccountId")]
        public int? AccountId
        {
            get => _AccountId;
            set
            {
                if (_AccountId != value)
                {
                    OnAccountIdChanging(value);
                    SendPropertyChanging();
                    _AccountId = value;
                    SendPropertyChanged("AccountId");
                    OnAccountIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("CallbackSalt")]
        public string CallbackSalt
        {
            get => _CallbackSalt;
            set
            {
                if (_CallbackSalt != value)
                {
                    OnCallbackSaltChanging(value);
                    SendPropertyChanging();
                    _CallbackSalt = value;
                    SendPropertyChanged("CallbackSalt");
                    OnCallbackSaltChanged();
                }
            }
        }

        [Column("UserSpaceId")]
        public int? UserSpaceId
        {
            get => _UserSpaceId;
            set
            {
                if (_UserSpaceId != value)
                {
                    OnUserSpaceIdChanging(value);
                    SendPropertyChanging();
                    _UserSpaceId = value;
                    SendPropertyChanged("UserSpaceId");
                    OnUserSpaceIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("Login")]
        public string Login
        {
            get => _Login;
            set
            {
                if (_Login != value)
                {
                    OnLoginChanging(value);
                    SendPropertyChanging();
                    _Login = value;
                    SendPropertyChanged("Login");
                    OnLoginChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("Pwd")]
        public string Pwd
        {
            get => _Pwd;
            set
            {
                if (_Pwd != value)
                {
                    OnPwdChanging(value);
                    SendPropertyChanging();
                    _Pwd = value;
                    SendPropertyChanged("Pwd");
                    OnPwdChanged();
                }
            }
        }

        [Column("IsTechnicalAccount"), Required]
        public bool IsTechnicalAccount
        {
            get => _IsTechnicalAccount;
            set
            {
                if (_IsTechnicalAccount != value)
                {
                    OnIsTechnicalAccountChanging(value);
                    SendPropertyChanging();
                    _IsTechnicalAccount = value;
                    SendPropertyChanged("IsTechnicalAccount");
                    OnIsTechnicalAccountChanged();
                }
            }
        }

        [DataType(DataType.DateTime), Column("StatusDate")]
        public DateTime? StatusDate
        {
            get => _StatusDate;
            set
            {
                if (_StatusDate != value)
                {
                    OnStatusDateChanging(value);
                    SendPropertyChanging();
                    _StatusDate = value;
                    SendPropertyChanged("StatusDate");
                    OnStatusDateChanged();
                }
            }
        }

        [Column("BankStatusCode")]
        public int BankStatusCode
        {
            get => _BankStatusCode;
            set
            {
                if (_BankStatusCode != value)
                {
                    OnBankStatusCodeChanging(value);
                    SendPropertyChanging();
                    _BankStatusCode = value;
                    SendPropertyChanged("BankStatusCode");
                    OnBankStatusCodeChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(255), Column("PivotalAccount")]
        public string PivotalAccount
        {
            get => _PivotalAccount;
            set
            {
                if (_PivotalAccount != value)
                {
                    OnPivotalAccountChanging(value);
                    SendPropertyChanging();
                    _PivotalAccount = value;
                    SendPropertyChanged("PivotalAccount");
                    OnPivotalAccountChanged();
                }
            }
        }

        public List<Resultat> Resultats { get; set; }

        public CompanyType CompanyType
        {
            get => _CompanyType;
            set
            {
                var previousValue = _CompanyType;
                if (previousValue != value)
                {
                    SendPropertyChanging();
                    _CompanyType = value;
                    if (value != null)
                    {
                        CompanyTypeId = value.CompanyTypeId;
                    }
                    else
                    {
                        _CompanyTypeId = default;
                    }
                    SendPropertyChanged("CompanyType");
                }
            }
        }

        public Country Country
        {
            get => _Country;
            set
            {
                var previousValue = _Country;
                if (previousValue != value)
                {
                    SendPropertyChanging();
                    _Country = value;
                    _CountryId = value?.CountryId ?? default;
                    SendPropertyChanged("Country");
                }
            }
        }

        [Column("IsKycIdSent"), Required]
        public bool IsKycIdSent
        {
            get => _IsKycIdSent;
            set
            {
                if (_IsKycIdSent != value)
                {
                    OnIsKycIdSentChanging(value);
                    SendPropertyChanging();
                    _IsKycIdSent = value;
                    SendPropertyChanged("IsKycIdSent");
                    OnIsKycIdSentChanged();
                }
            }
        }

        public event PropertyChangingEventHandler PropertyChanging;

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void SendPropertyChanging()
        {
            PropertyChanging?.Invoke(this, emptyChangingEventArgs);
        }

        protected virtual void SendPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void Attach_Resultats(Resultat entity)
        {
            SendPropertyChanging();
            entity.Company = this;
        }

        private void Detach_Resultats(Resultat entity)
        {
            SendPropertyChanging();
            entity.Company = null;
        }
    }

et le script de création de table associé:

create table T_Companies
(
    CompanyId            int identity (10) identity
        primary key nonclustered,
    CompanyName          varchar(1024) not null,
    CompanyTypeId        int           not null
        constraint FK_Company_CompanyType
            references T_CompanyTypes,
    CountryId            int           not null
        constraint FK_Company_Country
            references T_Countries,
    Active               bit           not null,
    AccountId            int,
    CallbackSalt         varchar(1024),
    UserSpaceId          int,
    Login                varchar(1024),
    Pwd                  varchar(1024),
    StatusDate           datetime(23, 3),
    BankStatusCode       int           not null,
    PivotalAccount       varchar(255),
    IsTechnicalAccount   bit           not null,
    CompanyStreetAddress varchar(256),
    CompanyCity          varchar(256),
    CompanyZipCode       varchar(10),
    CompanyVatNumber     varchar(30),
    ContactFirstName     varchar(20),
    ContactLastName      varchar(20),
    IsKycIdSent          bit           not null
)
go

[EDIT 2]

Pour le même modèle, cela (dans le fichier projet les références du nuget) fonctionne

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.8" />

tandis que ceux-là, non:

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.8" />
7
Kerry Perret

Ce type d'exception peut également apparaître si vous activez la dernière fonctionnalité Nullable à partir de C # 8.

EF Core, au moins actuellement, il n'est pas entièrement compatible avec les types nullables C # 8. Ainsi, par exemple, étant donné que vous activez la fonction Nullable pour le projet, si vous avez un type comme celui-ci:

public class MyEntity
{
   public string MyProperty { get; set; }
}

même si la propriété n'est pas pas marquée avec l'attribut [Requis], EF core déclenche ce type d'exception car requiert = cette valeur dans la base de données n'est pas nulle (c'est-à-dire qu'elle ne teste pas la valeur de la colonne avec IsDbNull).

Pour plus d'informations sur la gestion des types de référence nullables dans le noyau EF, consultez: https://docs.Microsoft.com/en-us/ef/core/miscivers/nullable-reference-types

1
adospace