1. 使用[owned]时出错
一个model里面定义了一个[owned]的属性,例如:
public class Order
{
public int Id { get; set; }
public StreetAddress ShippingAddress { get; set; }
}
[Owned]
public class StreetAddress
{
public string Street { get; set; }
public string City { get; set; }
}
然后在通过api创建Order数据时报错如下:
System.InvalidOperationException: The entity of type 'Order' is sharing the table 'Order' with entities of type 'StreetAddress', but there is no entity of this type with the same key value '{Id: 7a69feac-6d28-4e2c-767a-08d7418bf87a}' that has been marked as 'Added'.
at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.Validate(Dictionary`2 sharedTablesCommandsMap)
at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.CreateModificationCommands(IReadOnlyList`1 entries, Func`1 generateParameterName)
at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IReadOnlyList`1 entries)+MoveNext()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
root cause:
在创建order数据时,没有StreetAddress的信息。原因在于Owned Types还不支持optional 类型(这里的nullable就是optional类型)。为了避免这个错,我们在创建数据时需要填一个空的object,
参考:
https://entityframeworkcore.com/knowledge-base/48063630/nullable-owned-types-in-ef-core
https://github.com/aspnet/EntityFramework.Docs/issues/466
2.定义的list类型但传人的json不是数组
报错如下:
Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List`1[quote.Models.Item]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\nPath 'items.quantity', line 12, position 19."
解决办发是将想创建的json数据当中的object类型改为数组类型,类似如下结构:
[{}]
3. 删除数据时报错
The DELETE statement conflicted with the REFERENCE constraint "FK_QuoteItem_Quote_QuoteId". The conflict occurred in database "SampleDB", table "dbo.QuoteItem", column 'QuoteId'.
The statement has been terminated.
4. 定义owned类型的数据的级联删除
not supported because the owned entity type 'Product' cannot be on the principal side of a non-ownership relationship
原因在于这里用来做principal side的属性本身是一个owned type。因此不能用做在定义级联删除时作为主表。
5. 循环引用
报错信息如下:
Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'item' with type 'quote.Models.Items'. Path '[0].items[0].product'.
原因在于在定义one to one的关系的时候,定义如下:
public class Item
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid itemId { get; set; }
public Product Product { get; set; }
}
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid productId { get; set; }
[ForeignKey("Item")]
public Guid itemId { get; set; }
public Item Item { get; set;}
}
当把product表中的Item字段拿掉之后,不再报错。
6.owned type的数据没有被一起更新
在调用put api更新数据时,put的api无法更新owned关系的数据。原因在于:
EF Core将owned类型当作没有identity的实体类型对待,因此指向owned类型的属性被视为navigation属性。 将父实体状态设置为“Modified”不会cascade级联到navigation属性。
但是,使用DbContext或DbSet的Update方法可以实现级联,因此,像下面这样使用时无法更新owned类型数据的:
_context.Entry(contactModelFromRequestBody).State = EntityState.Modified;
而应该用:
_context.Update(contactModelFromRequestBody);
或者也可以手动设置owned类型属性的更新状态。例如:
_context.Entry(quote.Customer).State = EntityState.Modified;
7. Unable to resolve service for type 'xxxxx' while attempting to activate xxxxx
root cause: 想在一个类中使用另一个类的方法,但是没有new这个类的实例,而是想使用依赖注入。于是在调用相应的类时报了这个错误。
解决办法,对于要使用依赖注入的类,需要在startup类当中的configureService方法加入类似如下的逻辑:
services.AddScoped<IDependencyOne, DependencyOne>(); <-- I was missing this line!
8.执行命令 dotnet ef database update报错
报错如下:
Could not execute because the specified command or file was not found.
Possible reasons for this include:
* You misspelled a built-in dotnet command.
* You intended to execute a .NET Core program, but dotnet-ef does not exist.
* You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH
解决方法,安装对应版本的.net core. 再执行命令:
dotnet tool install --global dotnet-ef
然后重启Powershell,运行成功
9.The instance of entity type 'Invoice' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key
在update一个entity多次时报错:
this.customTableDbContext.Set<TEntity>().Update(entity);
this.customTableDbContext.SaveChanges();
解决办法是:
this.customTableDbContext.Set<TEntity>().Update(entity);
this.customTableDbContext.SaveChanges();
this.customTableDbContext.Entry(entity).State = EntityState.Detached;
update之后将状态设置为Detached