许多实体框架核心的插入和更新

问题描述 投票:0回答:1

所以,让我解释一下。我有2张桌子:“旅程”和“地址”。多对多关系,带有一个称为JourneyAddress的额外表,其中包含ID的所有条目,就像普通的多对多关系一样。但是我不明白如何用新的地址来更新该表,每次我尝试更新它时都会在下面抛出异常。我试图删除所有带有旅程ID-地址ID的旧条目,然后插入新条目,但是那也不起作用,我想这不是处理多对多插入和更新的正确方法。

旅程舱:

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; }
    }
}

地址类别:

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; }

    }
}

数据库上下文:

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);
        }
    }
}

这里是JourneysController的“ PutJourney”方法:

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();
    }

这里是例外:

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)
c# entity-framework-core many-to-many
1个回答
0
投票

首先插入。试试这个。

var journeyAddress = _context.JourneyAddress.Where(p => p.journeyId == id);
_repo.Update(journey);
_context.JourneyAddress.RemoveRange(journeyAddress);
_context.SaveChanges();

_ repo.Update也将添加trip.journeyAddress。因此,您不必再次添加。

© www.soinside.com 2019 - 2024. All rights reserved.