如何解决对其他模型的多个导航属性重复使用外键
这是a corresponding github issue on the EF Core repo的交叉发布。
在polymorphic relations can be supported之前,我一直在尝试采用现有模式并从中创建一些有用的导航属性。不幸的是,尽管在感觉上我能够获得的最接近的途径是通过以下方面,但我在很多方面都受到挫败:
public class Entitlement
{
public Guid Id { get; set; }
public Guid EntitleableId { get; set; }
}
public class Tenant
{
public Guid Id { get; set; }
public ICollection<Entitlement> AssignedEntitlements { get; set; }
}
// note: Consider User and Firm the same as tenant in this example.
// ...
modelBuilder
.Entity<Tenant>()
.HasMany((tenant) => tenant.AssignedEntitlements)
.WithOne()
.Isrequired(true)
.HasForeignKey((entitlement) => entitlement.EntitleableId)
.HasPrincipalKey((tenant) => tenant.Id);
modelBuilder
.Entity<Firm>()
.HasMany((firm) => firm.AssignedEntitlements)
.WithOne()
.Isrequired(true)
.HasForeignKey((entitlement) => entitlement.EntitleableId)
.HasPrincipalKey((firm) => firm.Id);
modelBuilder
.Entity<User>()
.HasMany((user) => user.AssignedEntitlements)
.WithOne()
.Isrequired(true)
.HasForeignKey((entitlement) => entitlement.EntitleableId)
.HasPrincipalKey((user) => user.Id);
// ...
使用类似这样的东西时,我似乎无法检索到任何东西
dbContext.Tenants.Include((t) => t.AssignedEntitlements);
实体框架生成有效的查询(.ToQueryString()
):
SELECT t.id,t.created_at,t."default",t.deleted_at,t.label,t.name,t.updated_at,e.id,e.created_at,e.entitleable_id,e.entitleable_type,e.feature,e.source_id,e.source_type,e.updated_at
FROM tenants AS t
LEFT JOIN entitlements AS e ON t.id = e.entitleable_id
ORDER BY t.id,e.id
运行生成的sql会返回正确的数据,但是对查询对象运行.First(),FirstOrDefault(),etc...
的任何尝试似乎都会引起问题:
system.invalidOperationException: Sequence contains no matching element
at System.Linq.ThrowHelper.ThrowNoMatchException()
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source,Func`2 predicate)
at MyProject.Conventions.Feature..ctor(String name)
at lambda_method374(Closure,QueryContext,DbDataReader,ResultContext,SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.<PopulateIncludeCollection>g__ProcessCurrentElementRow|60_0[TIncludingEntity,TIncludedEntity](<>c__displayClass60_0`2& )
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.PopulateIncludeCollection[TIncludingEntity,TIncludedEntity](Int32 collectionId,QueryContext queryContext,DbDataReader dbDataReader,SingleQueryResultCoordinator resultCoordinator,Func`3 parentIdentifier,Func`3 outerIdentifier,Func`3 selfIdentifier,IReadOnlyList`1 parentIdentifierValueComparers,IReadOnlyList`1 outerIdentifierValueComparers,IReadOnlyList`1 selfIdentifierValueComparers,Func`5 innerShaper,INavigationBase inverseNavigation,Action`2 fixup,Boolean trackingQuery)
at lambda_method376(Closure,SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at lambda_method377(Closure,QueryContext )
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
at MyProject.Global.Api.Controller.TestController.Test(MyProjectGlobalContext context) in /home/me/Development/MyProject/global/MyProject.Global.Api/src/Controller/TestController.cs:line 19
at lambda_method289(Closure,Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper,ObjectMethodExecutor executor,Object controller,Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
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 ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker,Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint,Task requestTask,ILogger logger)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next,HttpContext context,AuthorizationPolicy policy,PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
解决方法
看起来像您的代码会导致此异常。 MyProject.Conventions.Feature
构造函数包含为某些空记录集调用First
扩展名的代码。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。