I've been trying to take advantage of a new way of creating many-to-many relationships - nice article about EF 5 many-to-many relationships.
The article states that you no longer need to define relation class and the framework does the job for you.
However, for a couple of hours now I've been struggling to add an existing entity to the collection of another entity.
My models
public record Bottle
{
[Key]
public int Id { get; set; }
[Required]
public string Username { get; set; }
// some other properties
public Collection<User> Owners { get; set; }
}
public record User
{
[Key]
public int Id { get; set; }
// some other properties
public Collection<Bottle> Bottles { get; set; }
}
Say that I want to add a new bottle to the database. I also know owners of that bottle. I had thought that this bit of code could work:
public async Task<int> AddBottle(BottleForAddition bottle)
{
var bottleEntity = mapper.Map<Bottle>(bottle);
bottleEntity.Owners = bottle
.OwnerIds // List<int>
.Select(id => new User { Id = id })
.ToCollection(); // my extension method
var createdEntity = await context.AddEntityAsync(bottleEntity);
await context.SaveChangesAsync();
return createdEntity.Entity.Id;
}
but sadly it does not work (BottleForAddition is DTO with almost the same properties).
I get this error:
Unable to create bottle (error: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 19: 'NOT NULL constraint failed: Users.Username'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at ...
So I came up with this
public async Task<int> AddBottle(BottleForAddition bottle)
{
var bottleEntity = mapper.Map<Bottle>(bottle);
bottleEntity.Owners = (await context.Users
.Where(u => bottle.OwnerIds.Contains(u.Id))
.ToListAsync())
.ToCollection();
var createdEntity = await context.AddEntityAsync(bottleEntity);
await context.SaveChangesAsync();
return createdEntity.Entity.Id;
}
That works but I have to fetch Users from the database.
Do you know about a better way how to deal with it?