I am encoutering error
System.NotSupportedException: коллекция доступна только для чтения
при выборе агрегата фильма с сервера sql с помощью EfCore следующим образом:
var film = await dbContext.Films
.Include(f => f.CountryItems)
.FirstOrDefaultAsync(f => f.Id == FilmId.Of(query.id), cancellationToken)
Мой агрегатор фильмов выглядит так:
public class Film : Aggregate<FilmId>
{
private readonly List<CountryItem> _filmCountries = [];
public IReadOnlyList<CountryItem> CountryItems => _filmCountries.AsReadOnly();
...
}
Сущность CountryItem выглядит следующим образом:
public class CountryItem : Entity<FilmCountryId>
{
protected CountryItem() { }
internal CountryItem(CountryName name, FilmId filmId)
{
Name = name;
FilmId = filmId;
}
public CountryName Name { get; private set; } = default!;
public FilmId FilmId { get; private set; } = default!;
}
Конфигурация фильма для миграции:
public class FilmsConfiguration : IEntityTypeConfiguration<Film>
{
public void Configure(EntityTypeBuilder<Film> builder)
{
builder.HasKey(f => f.Id);
builder.Property(f => f.Id)
.HasConversion(filmid => filmid.Value, f => FilmId.Of(f))
.ValueGeneratedOnAdd()
.UseIdentityColumn();
builder.HasMany(f => f.CountryItems)
.WithOne()
.HasForeignKey(c => c.FilmId);
}
}
Конфигурация CountryItem:
public class CountryItemsConfiguration : IEntityTypeConfiguration<CountryItem>
{
public void Configure(EntityTypeBuilder<CountryItem> builder)
{
builder.HasKey(c => c.Id);
builder.Property(c => c.Id)
.HasConversion(c => c.Value, id => FilmCountryId.Of(id))
.ValueGeneratedOnAdd()
.UseIdentityColumn();
builder.Property(c => c.Name).HasMaxLength(50).IsRequired()
.HasConversion(c => c.Value, name => CountryName.Of(name));
builder.Property(c => c.FilmId)
.HasConversion(c => c.Value, c => FilmId.Of(c))
.IsRequired();
}
}
Кто-нибудь может сказать, что может пойти не так в этом случае? Потому что в этом случае это работает в другом проекте:
var orders = await dbContext.Orders
.Include(o => o.OrderItems)
.FirstOrDefaultAsync(o=>o.Id == OrderId.Of(new Guid("7e761dbd-1aaa-4640-8db6-d12a883e4080")),cancellationToken);
public class Order : Aggregate<OrderId>
{
private readonly List<OrderItem> _orderItems = new();
public IReadOnlyCollection<OrderItem> OrderItems => _orderItems.AsReadOnly();
...
}
public class OrderItem : Entity<OrderItemId>
{
protected OrderItem() { }
internal OrderItem(OrderId orderId, ProductId productId, int quantity, decimal price)
{
Id = OrderItemId.Of(Guid.NewGuid());
OrderId = orderId;
ProductId = productId;
Quantity = quantity;
Price = price;
}
public OrderId OrderId { get; private set; } = default!;
public ProductId ProductId { get; private set; } = default!;
public int Quantity { get; private set; } = default!;
public decimal Price { get; private set; } = default!;
}
public class OrderConfiguration : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).HasConversion(
orderId => orderId.Value,
dbId => OrderId.Of(dbId));
builder.HasMany(o => o.OrderItems)
.WithOne()
.HasForeignKey(oi => oi.OrderId);
}
}
public class OrderItemConfiguration : IEntityTypeConfiguration<OrderItem>
{
public void Configure(EntityTypeBuilder<OrderItem> builder)
{
builder.HasKey(oi => oi.Id);
builder.Property(oi => oi.Id).HasConversion(
orderItemId => orderItemId.Value,
dbId => OrderItemId.Of(dbId));
builder.HasOne<Product>()
.WithMany()
.HasForeignKey(oi => oi.ProductId);
builder.Property(oi => oi.Quantity).IsRequired();
builder.Property(oi => oi.Price).IsRequired();
}
}
@SvyatlavDanyliv Я добавил в свой вопрос пример заказа, который работает в другом проекте. Я нашел этот пример в курсовом проекте Udemy. Я даже пытался добавить этот пример фильма в этот проект, и он выдавал ту же ошибку. Потом я попробовал много вещей в этом проекте, и через некоторое время это сработало. Думал, что изменение имени должно что-то сделать с миграциями (изменили модель страны на CountryItem), но это тоже не тот случай.
Ну, вероятно, EF Core нашел резервное поле _orderItems
по соглашению по OrderItems
имени. В вашем случае это невозможно. Название `_filmCountries` слишком далеко от CountryItems
. Итак, попробуйте переименовать _filmCountries
в _countryItems
.
МОЙ БОГ. Это сработало, большое спасибо. Я потратил на это 24 часа :D
Вы можете добавить этот ответ, и я отмечу его как ответ @SvyatlavDanyliv
На основе документации о том, как EF Core находит резервные поля. Вам следует переименовать поле _filmCountries
в _countryItems
.
Это позволит автоматически решить, как хранить значение для свойств, доступных только для чтения.
Показать другие объекты. Странно, что они работают.