I am getting the following error when try and add a new Author object to the AuthorsDbSet and unsure of how to resolve it.
{"No coercion operator is defined between types 'System.Collections.Generic.List
1[Persistence.Entities.Book]' and 'System.Collections.ObjectModel.ReadOnlyCollection1[Persistence.Entities.Book]'."}
Method that causes exception when adding entity to db set:
public async Task<Guid> CreateAuthorAsync(string name)
{
ArgValidator.ThrowIfNullEmptyOrWhiteSpace(name);
using var context = _dbContextFactory.CreateDbContext();
var author = Author.Create(name);
context.Authors.Add(author);//this line throws the exception
await context.SaveChangesAsync();
return author.Id;
}
Author Class
public class Author
{
public Guid Id { get; }
public string Name { get; }
public ReadOnlyCollection<Book> Books => _books.AsReadOnly();
private List<Book> _books = new List<Book>();
private Author(Guid id, string name)
{
Id = id;
Name = name;
}
public static Author Create(string name)
{
ArgValidator.ThrowIfNullEmptyOrWhiteSpace(name);
return new Author(Guid.NewGuid(), name);
}
}
Book Class
public class Book
{
public Guid Id { get; }
public string Title { get; }
public string Description { get; }
public Author Author { get; }
public Guid AuthorId { get; }
public bool Available { get; private set; }
private Book(Guid id, string title, string description, bool available, Guid authorId)
{
Id = id;
Title = title;
Description = description;
Available = available;
AuthorId = authorId;
}
public static Book Create(string title, string description, Guid authorId)
{
ArgValidator.ThrowIfNullEmptyOrWhiteSpace(title);
description = description ?? string.Empty;
return new Book(Guid.NewGuid(), title, description, true, authorId);
}
DbContext
public class LibraryContext: DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
public LibraryContext(DbContextOptions<LibraryContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>(e =>
{
e.ToTable("Books", b => b.IsTemporal());
e.HasKey(x => x.Id);
e.Property(x => x.Title).IsRequired();
e.Property(x => x.Description).IsRequired();
e.Property(x => x.Available).IsRequired().HasDefaultValue(false);
e.HasOne(book => book.Author).WithMany(author => author.Books).HasForeignKey(book => book.AuthorId);
});
modelBuilder.Entity<Author>(e =>
{
e.ToTable("Authors", a => a.IsTemporal());
e.HasKey(x => x.Id);
e.Property(x => x.Name).IsRequired();
e.HasMany(author => author.Books).WithOne(book => book.Author);
//not explicitly configuring field as there is no proper fluent api method for it.
//https://stackoverflow.com/questions/60617430/ef-core-3-configure-backing-field-of-navigation-property
//simply allow it to be pickedup in the background by convention.
});
}
I'm not sure if it is as a result of the the onModelCreating code not being correct or something else. Perhaps I need to define some sort of coercion operator for List and Readonly collection, how would I do that?
Resolved this by changing to IList and IReadonlyCollection. Leaving question up as I couldn't find similar issue when searching.