我在创建书Book/Create时遇到此错误
PostgresException:23503:“ Books”表违反了“ FK_Books客户BorrowerId”外键约束冲突 Npgsql.NpgsqlConnector + d__148.MoveNext()
DbUpdateException:更新条目时发生错误。有关详细信息,请参见内部异常。 Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection连接)
我需要修复它吗?
LibraryDbContext.cs:
using LibraryManagement.Data.Model;
using Microsoft.EntityFrameworkCore;
namespace LibraryManagement.Data
{
public class LibraryDbContext : DbContext
{
public LibraryDbContext(DbContextOptions<LibraryDbContext> options) : base(options)
{
}
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Book>()
.HasOne(b => b.Borrower)
.WithMany()
.HasForeignKey(a => a.BorrowerId);
// https://github.com/aspnet/EntityFrameworkCore/issues/3924
// EF Core 2 doesnt support Cascade on delete for in Memory Database
base.OnModelCreating(builder);
}
}
}
CustomerRepository.cs:
using LibraryManagement.Data.Interfaces;
using LibraryManagement.Data.Model;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using System;
namespace LibraryManagement.Data.Repository
{
public class CustomerRepository : Repository<Customer>, ICustomerRepository
{
public CustomerRepository(LibraryDbContext context) : base(context) { }
public override void Delete(Customer entity)
{
_context.Books.Where(b => b.Borrower == entity)
.ToList()
.ForEach(a =>
{
a.Borrower = null;
a.BorrowerId = 0;
});
base.Delete(entity);
}
}
}
BookRepository.cs:
using LibraryManagement.Data.Interfaces;
using LibraryManagement.Data.Model;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using System;
namespace LibraryManagement.Data.Repository
{
public class BookRepository : Repository<Book>, IBookRepository
{
public BookRepository(LibraryDbContext context) : base(context) { }
public IEnumerable<Book> FindWithAuthor(Func<Book, bool> predicate)
{
return _context.Books
.Include(a => a.Author)
.Where(predicate);
}
public IEnumerable<Book> FindWithAuthorAndBorrower(Func<Book, bool> predicate)
{
return _context.Books
.Include(a => a.Author)
.Include(a => a.Borrower)
.Where(predicate);
}
public IEnumerable<Book> GetAllWithAuthor()
{
return _context.Books.Include(a => a.Author);
}
}
}
Repository.cs:
using LibraryManagement.Data.Interfaces;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace LibraryManagement.Data.Repository
{
public abstract class Repository<T> : IRepository<T> where T : class
{
protected readonly LibraryDbContext _context;
public Repository(LibraryDbContext context)
{
_context = context;
}
protected void Save() => _context.SaveChanges();
public void Create(T entity)
{
_context.Add(entity);
Save();
}
public virtual void Delete(T entity)
{
_context.Remove(entity);
Save();
}
public IEnumerable<T> GetAll()
{
return _context.Set<T>();
}
public T GetById(int id)
{
return _context.Set<T>().Find(id);
}
public void Update(T entity)
{
_context.Entry(entity).State = EntityState.Modified;
Save();
}
public IEnumerable<T> Find(Func<T, bool> predicate)
{
return _context.Set<T>().Where(predicate);
}
public int Count(Func<T, Boolean> predicate)
{
return _context.Set<T>().Where(predicate).Count();
}
public bool Any(Func<T, bool> predicate)
{
return _context.Set<T>().Any(predicate);
}
public bool Any()
{
return _context.Set<T>().Any();
}
}
}
BookController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using LibraryManagement.Data.Interfaces;
using LibraryManagement.Data.Model;
using LibraryManagement.ViewModels;
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace LibraryManagement.Controllers
{
public class BookController : Controller
{
private readonly IBookRepository _repository;
private readonly IAuthorRepository _authorRepository;
public BookController(IBookRepository repository, IAuthorRepository authorRepository)
{
_repository = repository;
_authorRepository = authorRepository;
}
[Route("Book")]
public IActionResult List(int? authorId, int? borrowerId)
{
var book = _repository.GetAllWithAuthor().ToList();
IEnumerable<Book> books;
ViewBag.AuthorId = authorId;
if(borrowerId != null)
{
books = _repository.FindWithAuthorAndBorrower(x => x.BorrowerId == borrowerId);
return CheckBooksCount(books);
}
if (authorId == null)
{
books = _repository.GetAllWithAuthor();
return CheckBooksCount(books);
}
else
{
var author = _authorRepository.GetWithBooks((int)authorId);
if (author.Books == null || author.Books.Count == 0)
return View("EmptyAuthor", author);
}
books = _repository.FindWithAuthor(a => a.Author.AuthorId == authorId);
return CheckBooksCount(books);
}
private IActionResult CheckBooksCount(IEnumerable<Book> books)
{
if (books == null || books.ToList().Count == 0)
{
return View("Empty");
}
else
{
return View(books);
}
}
public IActionResult Update(int id)
{
Book book = _repository.FindWithAuthor(a => a.BookId == id).FirstOrDefault();
if (book == null)
{
return NotFound();
}
var bookVM = new BookEditViewModel
{
Book = book,
Authors = _authorRepository.GetAll()
};
return View(bookVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Update(BookEditViewModel bookVM)
{
if (!ModelState.IsValid)
{
bookVM.Authors = _authorRepository.GetAll();
return View(bookVM);
}
_repository.Update(bookVM.Book);
return RedirectToAction("List");
}
public IActionResult Create(int? authorId)
{
Book book = new Book();
if(authorId != null)
{
book.AuthorId = (int)authorId;
}
var bookVM = new BookEditViewModel
{
Authors = _authorRepository.GetAll(),
Book = book
};
return View(bookVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(BookEditViewModel bookVM)
{
if (!ModelState.IsValid)
{
bookVM.Authors = _authorRepository.GetAll();
return View(bookVM);
}
_repository.Create(bookVM.Book);
return RedirectToAction("List");
}
public IActionResult Delete(int id, int? authorId)
{
var book = _repository.GetById(id);
_repository.Delete(book);
return RedirectToAction("List", new { authorId });
}
}
}
堆栈:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Npgsql.PostgresException: 23503: "Books" tablosu üzende işlem "FK_Books_Customers_BorrowerId" foreign key constrainti ihlal ediyor
at Npgsql.NpgsqlConnector.<DoReadMessage>d__148.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlConnector.<ReadMessage>d__147.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Npgsql.NpgsqlConnector.<ReadMessage>d__147.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlDataReader.<NextResult>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.<Execute>d__71.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__92.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(Tuple`2 parameters)
at Microsoft.EntityFrameworkCore.Storage.Internal.NpgsqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at LibraryManagement.Data.Repository.Repository`1.Save() in C:\Users\Pentest\Desktop\Prismacsi\Prismacsi-Staj\Data\Repository\Repository.cs:line 18
at LibraryManagement.Data.Repository.Repository`1.Create(T entity) in C:\Users\Pentest\Desktop\Prismacsi\Prismacsi-Staj\Data\Repository\Repository.cs:line 24
at LibraryManagement.Controllers.BookController.Create(BookEditViewModel bookVM) in C:\Users\Pentest\Desktop\Prismacsi\Prismacsi-Staj\Controllers\BookController.cs:line 130
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.<ExecuteWithFilter>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()