Почему SqlServer предполагает, что принадлежащий двойной вложенности объект не имеет значения NULL?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Почему SqlServer предполагает, что принадлежащий двойной вложенности объект не имеет значения NULL?

Сообщение Anonymous »

Описание
  • По сути, я пытаюсь получить результат (здесь он называется Foo) с некоторыми деталями (здесь он называется Bar )

    Детали не являются обязательными (например, может возникнуть ошибка)
  • Детали содержат множество вещей, в том числе другая сущность (здесь она называется Баз).
  • не требуется, но при его установке также должен быть установлен Baz.
  • Тип Baz используется, поскольку тип Baz используется повторно несколько раз.
[*]При попытке загрузить элемент из базы данных ошибочно предполагает, что Баз не имеет значения NULL, даже если объект Bar имеет значение NULL (и, следовательно, Baz также должен иметь значение NULL).
  • По крайней мере, это мое текущее понимание проблемы.
[*]Эта проблема специфична для SqlServer и не возникает с базой данных в памяти.

Вопрос: Почему это вызывает проблемы и как правильно указать эту связь?
Вопрос: есть ли какое-то обходное решение, чтобы это заработало?
Исключение

Код: Выделить всё

Unhandled exception. System.InvalidOperationException: An error occurred while reading a database value for property 'BazDto.BarDtoFooDtoId'. The expected type was 'System.Guid' but the actual value was null.
---> System.Data.SqlTypes.SqlNullValueException: Data is Null.  This method or property cannot be called on Null values.
at Microsoft.Data.SqlClient.SqlBuffer.ThrowIfNull()
at Microsoft.Data.SqlClient.SqlBuffer.get_Guid()
at Microsoft.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)
at lambda_method32(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
--- End of inner exception stack trace ---
at lambda_method32(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Program.Main(String[] args) in D:\paul\CODE\playground\Playground_02\ConsoleApp1\Program.cs:line 88
at Program.Main(String[] args) in D:\paul\CODE\playground\Playground_02\ConsoleApp1\Program.cs:line 88
at Program.(String[] args)
Воспроизводимый пример

Код: Выделить всё

public class FooDto
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }

public BarDto? Bar { get; set; }
}

[Owned]
public class BarDto
{
public BazDto Baz { get; set; } = null!;

// https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/breaking-changes#nested-optional-dependents-sharing-a-table-and-with-no-required-properties-are-disallowed
public int _RequiredFieldToAvoidWarning { get; set; }
}

[Owned]
public class BazDto
{
public int Id { get; set; }
}

public class ExampleContext : DbContext
{
public DbSet Foos { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
base.OnConfiguring(options);

options.EnableDetailedErrors();

options.UseLoggerFactory(LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Trace);
}));

var connectionString = @"CONNECTION_STRING"; // UPDATE
options.UseSqlServer(connectionString);
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity(fooBuilder =>
{
fooBuilder.OwnsOne(x => x.Bar, barBuilder =>
{
barBuilder
.OwnsOne(x => x.Baz, bazBuilder =>
{
// This is required for the issue to occur, there needs to be a separate table
bazBuilder.ToTable("Baz");
});
});
});
}
}

internal class Program
{
public static async Task Main(string[] args)
{
await using var context = new ExampleContext();

await context.Database.MigrateAsync();

context.Foos.Add(new FooDto()
{
Id = Guid.NewGuid(),
Bar = null,
});

await context.SaveChangesAsync();

// This will throw an exception
var result = await context.Foos
.AsNoTracking()
.Include(x => x.Bar)
.ThenInclude(x => x!.Baz)
.FirstAsync();
}
}
Журналы
Изначально я пытался включить журналы в вопрос, но они превышают максимальный размер.
Журналы можно найти здесь.


Подробнее здесь: https://stackoverflow.com/questions/790 ... s-not-null
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»