当我想更新实体时,我陷入了这个问题,这是我的存储库类:
private readonly CourseDbContext _dbContext;
public CourseRepository(CourseDbContext dbContext) : base(dbContext)
{
_dbContext = dbContext;
}
public async Task<Domain.Models.Course> GetAsync(Guid id, CancellationToken token)
{
return await _dbContext.Courses.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, token);
}
public async Task UpdateAsync(Domain.Models.Course model, CancellationToken token)
{
model.ModifiedAt = DateTimeOffset.Now;
EntityEntry<Domain.Models.Course> entry = _dbContext.Attach(model);
entry.Property(m => m.SeqId).IsModified = false;
entry.Property(m => m.CreatedAt).IsModified = false;
_dbContext.Update(model);
await _dbContext.SaveChangesAsync(token).ConfigureAwait(false);
}
这是我的CourseDbContext类:
public class CourseDbContext : DbContext
{
public CourseDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CourseConfiguration());
}
//add dbsets
}
注册CourseDbContext:
services.AddDbContextPool<CourseDbContext>(options =>
{
options.UseSqlServer(configuration.GetValue<string>("CourseMSSQL"));
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}, 1024);
我的控制器:
[HttpPut("{id:guid}")]
public async Task UpdateAsync(Guid id, [FromForm] CourseCreateRequest request)
{
var entity = await _repository.GetAsync(id, HttpContext.RequestAborted);
await _repository.UpdateAsync(entity, HttpContext.RequestAborted);
}
当我尝试更新课程实体时,在EntityEntry<Domain.Models.Course> entry = _dbContext.Attach(model);
中引发此异常:
"ClassName": "System.ArgumentException",
"Message": "Argument types do not match",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": " at System.Linq.Expressions.Expression.Condition(Expression test, Expression ifTrue, Expression ifFalse)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SnapshotFactoryFactory.CreateSnapshotValueExpression(Expression expression, IPropertyBase propertyBase)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SnapshotFactoryFactory.CreateSnapshotExpression(Type entityType, ParameterExpression parameter, Type[] types, IList`1 propertyBases)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SnapshotFactoryFactory.CreateConstructorExpression(IEntityType entityType, ParameterExpression parameter)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SnapshotFactoryFactory`1.Create(IEntityType entityType)\r\n at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.<>c.<get_OriginalValuesFactory>b__147_0(EntityType entityType)\r\n at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)\r\n at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.get_OriginalValuesFactory()\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.OriginalValues..ctor(InternalEntityEntry entry)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.EnsureOriginalValues()\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntrySubscriber.SnapshotAndSubscribe(InternalEntityEntry entry)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)\r\n at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)\r\n at Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)\r\n at Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState)\r\n at Microsoft.EntityFrameworkCore.DbContext.Attach[TEntity](TEntity entity)\r\n at CLive.Course.Repository.Implementation.CourseRepository.UpdateAsync(Course model, CancellationToken token) in D:\\Projects\\clive\\src\\Course\\Course.Repository\\Implementation\\CourseRepository.cs:line 99\r\n at CLive.Course.Api.Dashboard.Controllers.CourseController.UpdateAsync(Guid id, CourseCreateRequest request) in D:\\Projects\\clive\\src\\Course\\Course.Api.Dashboard\\Controllers\\CourseController.cs:line 173\r\n at lambda_method(Closure , Object )\r\n at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)"
此课程实体配置:
public class CourseConfiguration : ModelBaseConfiguration<Domain.Models.Course>
{
public override void ConfigureDerived(EntityTypeBuilder<Domain.Models.Course> builder)
{
builder.Property(x => x.Title)
.HasMaxLength(512).IsRequired();
builder.Property(x => x.Field)
.HasConversion(
filed => filed.HasValue ? filed.Value.ToString("G") : null,
stringValue => string.IsNullOrEmpty(stringValue) ? default : (Field)Enum.Parse(typeof(Field), stringValue));
builder.Property(x => x.Grade)
.HasConversion(
grade => grade.HasValue ? grade.Value.ToString("G") : null,
stringValue => string.IsNullOrEmpty(stringValue) ? default : (Grade)Enum.Parse(typeof(Grade), stringValue));
builder.Property(x => x.CoverImage)
.HasMaxLength(256);
builder.Property(x => x.ThumbnailImage)
.HasMaxLength(256);
builder.HasOne(x => x.Teacher)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
var courseSchedulersComparer = new ValueComparer<IList<CourseScheduler>>(
(c1, c2) => c1.SequenceEqual(c2),
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
c => c.ToList());
builder.Property(x => x.CourseSchedulers)
.HasConversion(listObject => Serialize(listObject),
json => Deserialize<List<CourseScheduler>>(json))
.Metadata.SetValueComparer(courseSchedulersComparer);
}
}
我认为一切都很好,但我不知道为什么EF
引发异常。
答案 0 :(得分:3)
我认为它是 EF 中的一个错误,但您需要转换快照结果:
var courseSchedulersComparer = new ValueComparer<IList<CourseScheduler>>(
(c1, c2) => c1.SequenceEqual(c2),
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
c => (IList<CourseScheduler>)c.ToList()); // note: I have added cast (IList<CourseScheduler>);
您不能只返回相同的实例 c => c
,因为您需要返回值的快照。这意味着如果您向列表中添加一些项目,则快照实例必须保持不变。
答案 1 :(得分:1)
在我的评论之后:尝试改用以下ValueComparer
:
var courseSchedulersComparer = new ValueComparer<IList<CourseScheduler>>(
(c1, c2) => c1.SequenceEqual(c2),
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
c => c); // note: I have removed .ToList(); `c` is already of type `IList<CourseScheduler>`