.eax
.eax
CC#
Created by .eax on 3/7/2023 in #help
❔ EF Core many-to-many migration problems
I added a new entity VesselTransfer and added two one-to-many relationship to the Vessel entity, and added the configuration as shown in the code below to OnModelCreating. No problems with creating the migration and applying it to the DB, but now I'm getting this error during runtime Unable to determine the relationship represented by navigation 'Team.Persons' of type 'ICollection<Person>'.. On a entity and relationship that has no changes, and I'm getting some form of this exception on whatever query I run. The error has different entities and relationships depending on the query. I'm a bit of a loss on what is wrong as nothing seems wrong from the configurations.
public class VesselTransfer : BaseTrackedEntity
{
public DateTime Start { get; set; }
public DateTime End { get; set; }

[IsProjected] public int DropOffVesselId { get; set; }
public virtual Vessel DropOffVessel { get; set; }

[IsProjected] public int CollectVesselId { get; set; }
public virtual Vessel CollectVessel { get; set; }
}

public class Vessel : BaseEntityVortex
{
public string Name { get; set; }

public virtual ICollection<VesselTransfer> VesselTransferDropOffs { get; set; }
public virtual ICollection<VesselTransfer> VesselTransferCollections { get; set; }
}

// In db context
modelBuilder.Entity<Vessel>()
.HasMany(x => x.VesselTransferDropOffs)
.WithOne(x => x.DropOffVessel)
.HasForeignKey(x => x.DropOffVesselId)
.OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Vessel>()
.HasMany(x => x.VesselTransferCollections)
.WithOne(x => x.CollectVessel)
.HasForeignKey(x => x.CollectVesselId)
.OnDelete(DeleteBehavior.Restrict);
public class VesselTransfer : BaseTrackedEntity
{
public DateTime Start { get; set; }
public DateTime End { get; set; }

[IsProjected] public int DropOffVesselId { get; set; }
public virtual Vessel DropOffVessel { get; set; }

[IsProjected] public int CollectVesselId { get; set; }
public virtual Vessel CollectVessel { get; set; }
}

public class Vessel : BaseEntityVortex
{
public string Name { get; set; }

public virtual ICollection<VesselTransfer> VesselTransferDropOffs { get; set; }
public virtual ICollection<VesselTransfer> VesselTransferCollections { get; set; }
}

// In db context
modelBuilder.Entity<Vessel>()
.HasMany(x => x.VesselTransferDropOffs)
.WithOne(x => x.DropOffVessel)
.HasForeignKey(x => x.DropOffVesselId)
.OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Vessel>()
.HasMany(x => x.VesselTransferCollections)
.WithOne(x => x.CollectVessel)
.HasForeignKey(x => x.CollectVesselId)
.OnDelete(DeleteBehavior.Restrict);
4 replies
CC#
Created by .eax on 10/25/2022 in #help
Have to call .ToList() on DbSets for .First() or .Single() to work. Sqlite
I have a simple dependency on a database, the schema contains 2 entities and I'm having some simple problems with making it work. I have to call ToList on the DbSets of the entities to make Single/First match elements. Anyone got any idea on whats wrong? I add the context in Program.cs like this:
builder.Services.AddDbContext<SibusyContext>();
builder.Services.AddDbContext<SibusyContext>();
Context looks like this:
public class SibusyContext : DbContext
{
private string DbPath { get; }

public DbSet<Pipeline> Pipelines { get; set; }
public DbSet<Job> Jobs { get; set; }

public SibusyContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
Console.WriteLine(path);
DbPath = Path.Join(path, "sibusy.db");
}

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"Data Source={DbPath}");
}
}
public class SibusyContext : DbContext
{
private string DbPath { get; }

public DbSet<Pipeline> Pipelines { get; set; }
public DbSet<Job> Jobs { get; set; }

public SibusyContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
Console.WriteLine(path);
DbPath = Path.Join(path, "sibusy.db");
}

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite($"Data Source={DbPath}");
}
}
And I use it in a service like this:
public interface IJobService
{
Task<string> ParseJob(CollectInput input, Guid pipelineId, CancellationToken ct);
}

public sealed class JobService : IJobService
{
private readonly SibusyContext _sibusyContext;
private readonly IMapper _mapper;

public JobService(SibusyContext sibusyContext, IMapper mapper)
{
_sibusyContext = sibusyContext;
_mapper = mapper;
}


public async Task<string> ParseJob(JobInput input, Guid pipelineId, CancellationToken cancellationToken)
{
var first = _sibusyContext.Pipelines.First();
var isTrue = first.Id == pipelineId; // this is true
var pipeline = _sibusyContext.Pipelines.FirstOrDefault(x => x.Id == pipelineId); // this is null
var works = _sibusyContext.Pipelines.ToList().FirstOrDefault(x => x.Id == pipelineId); // this works
if (pipeline is null)
return "TODO";

var job = _mapper.Map<Job>(input);

job.PipelineId = pipelineId;
await _sibusyContext.AddAsync(job, cancellationToken);
await _sibusyContext.SaveChangesAsync(cancellationToken);

return "TODO";
}
}
public interface IJobService
{
Task<string> ParseJob(CollectInput input, Guid pipelineId, CancellationToken ct);
}

public sealed class JobService : IJobService
{
private readonly SibusyContext _sibusyContext;
private readonly IMapper _mapper;

public JobService(SibusyContext sibusyContext, IMapper mapper)
{
_sibusyContext = sibusyContext;
_mapper = mapper;
}


public async Task<string> ParseJob(JobInput input, Guid pipelineId, CancellationToken cancellationToken)
{
var first = _sibusyContext.Pipelines.First();
var isTrue = first.Id == pipelineId; // this is true
var pipeline = _sibusyContext.Pipelines.FirstOrDefault(x => x.Id == pipelineId); // this is null
var works = _sibusyContext.Pipelines.ToList().FirstOrDefault(x => x.Id == pipelineId); // this works
if (pipeline is null)
return "TODO";

var job = _mapper.Map<Job>(input);

job.PipelineId = pipelineId;
await _sibusyContext.AddAsync(job, cancellationToken);
await _sibusyContext.SaveChangesAsync(cancellationToken);

return "TODO";
}
}
7 replies