Как решить SqlNullValueException? - PullRequest
       8

Как решить SqlNullValueException?

4 голосов
/ 24 января 2020

Я пытаюсь найти сущность, но я получаю SqlNullValueException, когда структура сущностей пытается получить значение поля, которое имеет значение Null.

Я проверил в базе данных, и все поля, не имеющие значения NULL, заполнены. , Единственными полями, которые имеют значение NULL, являются те, которые могут иметь его.

В других ответах я обнаружил, что должен удалить обязательный атрибут из свойств класса или удалить метод IsRequired из определения модели, однако я они автоматически сгенерированы, и у них никогда не было требуемого определения.

Мое приложение работает на. NET Core 3.1, а мой EntityFrameworkCore - версия 2.2.4. Даже если он успешно строится, может ли это вызвать проблему? Обновление Сейчас все версии 3.1.

Если нет, то что еще может вызвать это?

Чтобы найти сущность, я использую следующий метод:

public static CodeLists FindCodeListById(Guid id)
{
    using (var context = new classificatielocalContext())
    {
        return context.CodeLists.Find(id);
    }
}

Однако я получаю следующее исключение:

System.Data.SqlTypes.SqlNullValueException

HResult = 0x80131931

Сообщение = данные равны нулю. Этот метод или свойство нельзя вызывать для значений Null.

Source = System.Data.Common

StackTrace:

при System.Data.SqlTypes.SqlGuid.get_Value()

при System.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)

в Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)

в Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 1.Enumerator.BufferlessMoveNext (DbContext _, логический буфер) `

при Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func 3 операции, Fun c3 verifySucceeded)

в Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 1.Enumerator.MoveNext () `

в System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable 1 источник, логическое значение и найдено)`

в Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable 1.GetEnumerator () `

в Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__17 2.MoveNext ()`

в Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor 1.EnumeratorExceptionInterceptor.MoveNext () `

в System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable 1 источник, логическое и найдено) `

в System.Linq.Enumerable.First[TSource](IEnumerable 1 источник)`

в Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1 1.b__0 (QueryContext q c) `

в Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)

в Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)

в System.Linq.Queryable.FirstOrDefault[TSource](IQueryable 1 источнике, выражение 1 predicate)

в Microsoft.EntityFrameworkCore.Internal.EntityFinder 1.Find (Object [] keyValues) `

в Microsoft.EntityFrameworkCore.Internal.InternalDbSet 1.Find (Object [] keyValues) `

в dal.Views.FindCodeListById(Guid id) in ...

в services.CodeListService.GetCodeList(Guid id) in ...

в api.Controllers.CodeListController.Get(Guid id) в ...

в Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)

в * 1 097 *

в Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()

Я использую OnModelCreating(ModelBuilder modelBuilder) для определения своих сущностей, и я не указал, где требуются мои столбцы.

Здесь мое определение модельера:

modelBuilder.Entity<CodeLists>(entity =>
{
    entity.HasKey(e => e.Id)
        .ForSqlServerIsClustered(false);

    entity.ToTable("code_lists");

    entity.Property(e => e.Id)
        .HasColumnName("id")
        .HasDefaultValueSql("(newsequentialid())");

    entity.Property(e => e.ClassificationId).HasColumnName("classification_id");

    entity.Property(e => e.DescriptionId).HasColumnName("description_id");

    entity.Property(e => e.NameId).HasColumnName("name_id");

    entity.Property(e => e.OwnerId).HasColumnName("owner_id");

    entity.HasOne(d => d.Classification)
        .WithMany(p => p.CodeLists)
        .HasForeignKey(d => d.ClassificationId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("FK__code_list__class__5FB337D6");

    entity.HasOne(d => d.Description)
        .WithMany(p => p.CodeListsDescription)
        .HasForeignKey(d => d.DescriptionId)
        .HasConstraintName("FK__code_list__descr__60A75C0F");

    entity.HasOne(d => d.Name)
        .WithMany(p => p.CodeListsName)
        .HasForeignKey(d => d.NameId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("FK__code_list__name___619B8048");

    entity.HasOne(d => d.Owner)
        .WithMany(p => p.CodeLists)
        .HasForeignKey(d => d.OwnerId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("FK__code_list__owner__628FA481");
});

А вот мое sql определение

CREATE TABLE [dbo].[code_lists]
(
    [id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY NONCLUSTERED DEFAULT NEWSEQUENTIALID(),
    [classification_id] UNIQUEIDENTIFIER NULL FOREIGN KEY REFERENCES classifications(id), -- TODO: Should be set to NOT NULL
    [description_id] UNIQUEIDENTIFIER FOREIGN KEY REFERENCES translations(id),
    [name_id] UNIQUEIDENTIFIER NOT NULL FOREIGN KEY REFERENCES translations(id),
    [owner_id] UNIQUEIDENTIFIER NULL FOREIGN KEY REFERENCES users(id), -- TODO: Should be set to NOT NULL
)

Обновление После обновления версий и добавления пакета nuget System.Data.SqlClient трассировка стека несколько изменилась на:

System.Data.SqlTypes.SqlNullValueException

HResult = 0x80131931

Сообщение = данные равны нулю. Этот метод или свойство нельзя вызывать для значений Null.

Source = Microsoft.Data.SqlClient

StackTrace:

в Microsoft.Data.SqlClient.SqlBuffer.ThrowIfNull()

в Microsoft.Data.SqlClient.SqlBuffer.get_Guid()

в Microsoft.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)

в Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 1.Enumerator.MoveNext () `

в System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable 1 источник)`

в Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)

в Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)

в System.Linq.Queryable.FirstOrDefault[TSource](IQueryable 1 источнике) `

в cbs.classifications.dal.Views.FindCodeListById(Guid id) в ...

в cbs.classifications.services.CodeListService.GetCodeList(Guid id) в ...

в cbs.classifications.api.Controllers.CodeListController.Get(Guid id) в

в Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)

в Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)

в Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()

Обновлено Класс CodeLists

public partial class CodeLists
{
    public CodeLists()
    {
        Levels = new HashSet<Levels>();
        Nodes = new HashSet<Nodes>();
    }

    public Guid Id { get; set; }
    public Guid ClassificationId { get; set; }
    public Guid? DescriptionId { get; set; }
    public Guid NameId { get; set; }
    public Guid OwnerId { get; set; }

    public Classifications Classification { get; set; }
    public Translations Description { get; set; }
    public Translations Name { get; set; }
    public Users Owner { get; set; }
    public ICollection<Levels> Levels { get; set; }
    public ICollection<Nodes> Nodes { get; set; }
}

1 Ответ

1 голос
/ 27 января 2020

Вы должны пометить все свойства Nullable CodeLists с типами данных Nullable, как показано ниже:

public class CodeLists
{
    public Guid Id { get; set; }
    public Guid? ClassificationId { get; set; }
    public Guid? DescriptionId { get; set; }

    public Guid NameId { get; set; }
    public Guid? OwnerId { get; set; }

}

ClassificationId и OwnerId не допускают значения NULL в вашем классе CodeLists, но могут иметь значение NULL в ДБ

...