t-schreibs
t-schreibs

Reputation: 35

Why am I seeing a "No coercion operator is defined" exception when attempting to update a record with a backing field?

I might not fully understand how the backing fields work inside of EF Core, but I'm surprised to see this exception appear when I attempt to save records - and I haven't been able to find any information about it. I am using C# 9 records with change tracking turned off. This is in the context of an ASP.NET Core Web API with Entity Framework Core and a SQLite database. Here are some simplified data models which repro the error:

public record Parent(string Info)
{
    //Backing field
    private List<Child> children = new();

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; init; } = 0;
    public ImmutableList<Child> Children 
    { 
        get => children.ToImmutableList(); 
        init => children = value.ToList(); 
    }
}
public record Child(string Info)
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; init; } = 0;
}

The database context:

public class TestContext : DbContext
{
    public TestContext(DbContextOptions<TestContext> options) : base(options)
        { }

    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Children { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Parent>().HasMany(
            parent => parent.Children).WithOne();
    }
}

A little controller where I attempt to save a new Parent to the database:

[ApiController]
[Route("[controller]")]
public class ParentController : Controller
{
    private readonly TestContext _context;

    public ParentController(TestContext context) => _context = context;

    [HttpPost]
    public ActionResult Create()
    {
    //Exception thrown:    
    _context.Parents.Add(new("First")
        {
            Children = new List<Child>
            {
                new("First"),
                new("Second"),
                new("Third")
            }.ToImmutableList()
        });
        _context.SaveChanges();
        return Ok();
    }
    [HttpGet]
    public ActionResult<IEnumerable<Parent>> Get()
        => _context.Parents.Include(
            parent => parent.Children).ToList();
}

The exception thrown:

System.InvalidOperationException: 'No coercion operator is defined between types 'System.Collections.Generic.List`1[TestAPI.Models.Child]' and 'System.Collections.Immutable.ImmutableList`1[TestAPI.Models.Child]'.'

What's going on behind the scenes here? How do I get around this?

Upvotes: 0

Views: 851

Answers (1)

Ruikai Feng
Ruikai Feng

Reputation: 11546

I tried as below

public List<Child> ChildLsit => Children.ToList();

        [NotMapped]
        public ImmutableList<Child> Children
        {
            get => children.ToImmutableList();
            init => children = value.ToList();
        }

this time,it won't get the error you've shown, In my opinion,if you do want to set the property as ImmutableList,you could create a DTO/ViewModel and set the correspond property as ImmutableList then map it to your entity

Upvotes: 0

Related Questions