C# 多对多实体框架核心插入和更新
那么,让我解释一下。我有两张桌子:旅程和地址。多对多关系,具有一个名为JourneyAddress的额外表,该表包含ID的所有条目,就像普通的多对多关系一样。但我不知道如何用新地址更新该表,每次我试图更新它时,都会抛出下面的异常。我试图删除所有带有旅程id-地址id的旧条目,然后插入新条目,但这也不起作用,我认为这不是处理多对多插入和更新的正确方法 旅程等级:C# 多对多实体框架核心插入和更新,c#,entity-framework-core,many-to-many,C#,Entity Framework Core,Many To Many,那么,让我解释一下。我有两张桌子:旅程和地址。多对多关系,具有一个名为JourneyAddress的额外表,该表包含ID的所有条目,就像普通的多对多关系一样。但我不知道如何用新地址更新该表,每次我试图更新它时,都会抛出下面的异常。我试图删除所有带有旅程id-地址id的旧条目,然后插入新条目,但这也不起作用,我认为这不是处理多对多插入和更新的正确方法 旅程等级: using System; using System.Collections.Generic; using System.Compone
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace ApplicazioneAutotrasporti.Model
{
public class Journey
{
[Key]
public int id { get; set; }
public virtual ICollection<JourneyAddress> journeyAddress { get; set; }
[ForeignKey("vehicleId")]
public Vehicle vehicle { get; set; }
public int vehicleId { get; set; }
[ForeignKey("driverId")]
public Driver driver { get; set; }
public int driverId { get; set; }
public DateTime date { get; set; }
public string measureUnit { get; set; }
public float quantity { get; set; }
public float valueForUnit { get; set; }
public float timeStop { get; set; }
public float valueStopTime { get; set; }
public string customer { get; set; }
}
}
使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Text.Json.Serialization;
命名空间applicationeAutoTrasporti.Model
{
公务舱旅程
{
[关键]
公共int id{get;set;}
公共虚拟ICollection日志地址{get;set;}
[外键(“车辆ID”)]
公共车辆{get;set;}
public int vehicleId{get;set;}
[外键(“driverId”)]
公共驱动程序{get;set;}
public int driverId{get;set;}
公共日期时间日期{get;set;}
公共字符串measureUnit{get;set;}
公共浮点数{get;set;}
单位{get;set;}的公共浮点值
公共浮点时隙{get;set;}
公共浮点值stopTime{get;set;}
公共字符串customer{get;set;}
}
}
地址类别:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace ApplicazioneAutotrasporti.Model
{
public class Address
{
[Key]
public int id { get; set; }
[Required]
public string name { get; set; }
public virtual ICollection<JourneyAddress> JourneyAddress { get; set; }
}
}
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.Text.Json.Serialization;
命名空间applicationeAutoTrasporti.Model
{
公共课堂演讲
{
[关键]
公共int id{get;set;}
[必需]
公共字符串名称{get;set;}
公共虚拟ICollection日志地址{get;set;}
}
}
数据库上下文:
using Microsoft.EntityFrameworkCore;
using ApplicazioneAutotrasporti.Model;
namespace TranscoopTrips.Data
{
public class DatabaseContext : DbContext
{
public DatabaseContext (DbContextOptions<DatabaseContext> options)
: base(options)
{
}
public DbSet<Driver> Driver { get; set; }
public DbSet<Vehicle> Vehicle { get; set; }
public DbSet<Address> Address { get; set; }
public DbSet<Fuel> Fuel { get; set; }
public DbSet<Journey> Journey { get; set; }
public DbSet<Maintenance> Maintenance { get; set; }
public DbSet<JourneyAddress> JourneyAddress { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<JourneyAddress>()
.HasKey(bc => new { bc.journeyId, bc.addressId });
modelBuilder.Entity<JourneyAddress>()
.HasOne(bc => bc.journey)
.WithMany(b => b.journeyAddress)
.HasForeignKey(bc => bc.journeyId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<JourneyAddress>()
.HasOne(bc => bc.address)
.WithMany(c => c.JourneyAddress)
.HasForeignKey(bc => bc.addressId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Fuel>()
.HasOne(c => c.vehicle)
.WithMany(e => e.Fuels)
.HasForeignKey(c => c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Journey>()
.HasOne(c => c.vehicle)
.WithMany(e => e.Journeys)
.HasForeignKey(c => c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Journey>()
.HasOne(c => c.driver)
.WithMany(e => e.Journeys)
.HasForeignKey(c => c.driverId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Maintenance>()
.HasOne(c => c.vehicle)
.WithMany(e => e.Maintenances)
.HasForeignKey(c => c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
}
}
}
使用Microsoft.EntityFrameworkCore;
使用applicationeautorasporti.Model;
名称空间TranscoopTrips.Data
{
公共类DatabaseContext:DbContext
{
公共数据库上下文(DbContextOptions)
:基本(选项)
{
}
公共数据库集驱动程序{get;set;}
公共数据库集车辆{get;set;}
公共数据库集地址{get;set;}
公共数据库集燃料{get;set;}
公共数据库集旅程{get;set;}
公共数据库集维护{get;set;}
公共DbSet JourneyAddress{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity()
.HasKey(bc=>new{bc.journeyId,bc.addressId});
modelBuilder.Entity()
.HasOne(卑诗省=>卑诗省旅程)
.WithMany(b=>b.journeyAddress)
.HasForeignKey(bc=>bc.journeyId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity()
.HasOne(bc=>bc.address)
.WithMany(c=>c.JourneyAddress)
.HasForeignKey(bc=>bc.addressId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity()
.HasOne(c=>c.vehicle)
.有许多(e=>e.燃料)
.HasForeignKey(c=>c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity()
.HasOne(c=>c.vehicle)
.有许多(e=>e.行程)
.HasForeignKey(c=>c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity()
.HasOne(c=>c.driver)
.有许多(e=>e.行程)
.HasForeignKey(c=>c.driverId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity()
.HasOne(c=>c.vehicle)
.有许多(e=>e.维护)
.HasForeignKey(c=>c.vehicleId)
.OnDelete(DeleteBehavior.Cascade);
}
}
}
以下是来自JourneysController的“PutTourney”方法:
public async Task<IActionResult> PutJourney(int id, Journey journey)
{
if (id != journey.id)
{
return BadRequest();
}
_context.Entry(journey).State = EntityState.Modified;
try
{
var journeyAddress = _context.JourneyAddress.Where(p => p.journeyId == id);
_context.JourneyAddress.RemoveRange(journeyAddress);
_context.JourneyAddress.AddRange(journey.journeyAddress);
_repo.Update(journey);
var save = await _repo.SaveAsync(journey);
}
catch (DbUpdateConcurrencyException)
{
if (!JourneyExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
公共异步任务PutTourney(int-id,旅程)
{
if(id!=旅程.id)
{
返回请求();
}
_context.Entry(旅程).State=EntityState.Modified;
尝试
{
var journeyAddress=_context.journeyAddress.Where(p=>p.journeyId==id);
_context.JourneyAddress.RemoveRange(JourneyAddress);
_context.JourneyAddress.AddRange(旅程.JourneyAddress);
_回购更新(旅程);
var save=wait _repo.SaveAsync(旅程);
}
catch(DbUpdateConcurrencyException)
{
如果(!JourneyExists(id))
{
返回NotFound();
}
其他的
{
投掷;
}
}
返回NoContent();
}
例外情况如下:
System.InvalidOperationException: The instance of entity type 'JourneyAddress' cannot be tracked because another instance with the same key value for {'journeyId', 'addressId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NullableKeyIdentityMap`1.Add(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
at Microsoft.EntityFrameworkCore.DbContext.SetEntityStates(IEnumerable`1 entities, EntityState entityState)
at Microsoft.EntityFrameworkCore.DbContext.AddRange(IEnumerable`1 entities)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.AddRange(IEnumerable`1 entities)
at TranscoopTrips.Controllers.JourneysController.PutJourney(Int32 id, Journey journey) in D:\Davide\Progetti\In corso\TranscoopTrips\TranscoopTrips\Controllers\JourneysController.cs:line 86
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
System.InvalidOperationException:无法跟踪实体类型“JourneyAddress”的实例,因为已在跟踪另一个具有{journeyId',addressId}相同键值的实例。附着现有实体时,请确保仅附着一个具有给定键值的实体实例。考虑使用“dBraveTopStudioBuff.EnabelSythViDeAtGracg”来查看冲突的键值。
位于Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThroWideTityConflict(InternalEntityEntry)
在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey、InternalEntityEntry条目、Boolean updateDuplicate)
位于Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey,InternalEntityEntry)
位于Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NullableKeyIdentityMap`1.Add(InternalEntityEntry)
位于Microsoft.EntityFrameworkCore.ChangeTrac
var journeyAddress = _context.JourneyAddress.Where(p => p.journeyId == id);
_repo.Update(journey);
_context.JourneyAddress.RemoveRange(journeyAddress);
_context.SaveChanges();