簡體   English   中英

無法將可查詢方法轉換為可枚舉方法。 這可能是實體框架中的一個問題

[英]Unable to convert a queryable method to an enumerable method. This is likely an issue in Entity Framework

我正在創建一個有點復雜的查詢來檢索與實體的多對多關系。 這是創建查詢的代碼:

  protected virtual async Task<IQueryable<ContactWithNavigationProperties>> GetQueryForNavigationPropertiesAsync()
  {
    var dbContext = await GetDbContextAsync();
    return from contact in await GetDbSetAsync()
           join department in dbContext.Departments
             on contact.DepartmentId equals department.Id into departments
           from department in departments.DefaultIfEmpty()
           join client in dbContext.Clients
             on contact.ClientId equals client.Id into clients
           from client in clients.DefaultIfEmpty()
           join contactAddress in dbContext.Set<ContactAddress>()
             on contact.Id equals contactAddress.ContactId into contactAddresses
           from contactAddress in contactAddresses.DefaultIfEmpty()
           join contactEmailAddress in dbContext.Set<ContactEmailAddress>()
             on contact.Id equals contactEmailAddress.ContactId into contactEmailAddresses
           from contactEmailAddress in contactEmailAddresses.DefaultIfEmpty()
           join contactPhoneNumber in dbContext.Set<ContactPhoneNumber>()
             on contact.Id equals contactPhoneNumber.ContactId into contactPhoneNumbers
           from contactPhoneNumber in contactPhoneNumbers.DefaultIfEmpty()
           select new ContactWithNavigationProperties
           {
             Contact = contact,
             Department = department,
             Client = client,
             Addresses = (from ca in contactAddresses
                          join address in dbContext.Addresses
                            on ca.AddressId equals address.Id into addresses
                          from address in addresses.DefaultIfEmpty()
                          select address).ToList(),
             EmailAddresses = (from cea in contactEmailAddresses
                               join emailAddress in dbContext.EmailAddresses
                                 on cea.EmailAddressId equals emailAddress.Id into emailAddresses
                               from emailAddress in emailAddresses.DefaultIfEmpty()
                               select emailAddress).ToList(),
             PhoneNumbers = (from cpn in contactPhoneNumbers
                             join phoneNumber in dbContext.PhoneNumbers
                               on cpn.PhoneNumberId equals phoneNumber.Id into phoneNumbers
                             from phoneNumber in phoneNumbers.DefaultIfEmpty()
                             select phoneNumber).ToList()
           };
  }

執行此查詢后,我將收到以下異常:

2021-12-06 07:49:17.867 -06:00 [ERR] Unable to convert a queryable method to an enumerable method. This is likely an issue in Entity Framework, please file an issue at https://go.microsoft.com/fwlink/?linkid=2142044.
System.InvalidOperationException: Unable to convert a queryable method to an enumerable method. This is likely an issue in Entity Framework, please file an issue at https://go.microsoft.com/fwlink/?linkid=2142044.
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ConvertToEnumerable(MethodInfo queryableMethod, IEnumerable`1 arguments)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
   at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)
   at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PendingSelectorExpandingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryTranslationPreprocessor.Process(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at MyProject.Contacts.EfCoreContactRepository.GetListWithNavigationPropertiesAsync(String filterText, String name, String surname, String title, Nullable`1 lastContactDateMin, Nullable`1 lastContactDateMax, String note, Nullable`1 departmentId, Nullable`1 clientId, Nullable`1 primary, Nullable`1 active, String sorting, Int32 maxResultCount, Int32 skipCount, CancellationToken cancellationToken) in D:\Century\Internal\Clients.Link\Clients.Link\src\MyProject.EntityFrameworkCore\Contacts\EfCoreContactRepository.cs:line 54
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at MyProject.Contacts.ContactsAppService.GetListAsync(GetContactsInput input) in D:\Century\Internal\Clients.Link\Clients.Link\src\MyProject.Application\Contacts\ContactAppService.cs:line 59
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at lambda_method3642(Closure , Object )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.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>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

因此,在我提交錯誤之前,我希望實體框架專家可以查看我的查詢並指出任何明顯的問題。

這是我的 csproj 文件及其依賴項:

<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <RootNamespace>MyProject</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="Addresses\AddressesDataSeedContributorWithDependencies.cs" />
    <Compile Remove="Campaigns\CampaignsDataSeedContributor.cs" />
    <Compile Remove="ClientNeeds\ClientNeedsDataSeedContributor.cs" />
    <Compile Remove="Clients\ClientsDataSeedContributorWithDependencies.cs" />
    <Compile Remove="Contacts\ContactsDataSeedContributorWithDependencies.cs" />
    <Compile Remove="Countries\CountriesDataSeedContributor.cs" />
    <Compile Remove="Departments\DepartmentsDataSeedContributor.cs" />
    <Compile Remove="EmailAddresses\EmailAddressesDataSeedContributor.cs" />
    <Compile Remove="EntityFrameworkCore\MyProjectDataSeeder.cs" />
    <Compile Remove="LeadSources\LeadSourcesDataSeedContributor.cs" />
    <Compile Remove="Migrations\MyProjectDbContextModelSnapshot - Copy.cs" />
    <Compile Remove="Opportunities\OpportunitiesDataSeedContributorWithDependencies.cs" />
    <Compile Remove="Opportunities\OpportunityLineItemsDataSeedContributorWithDependencies.cs" />
    <Compile Remove="PhoneNumbers\PhoneNumbersDataSeedContributor.cs" />
    <Compile Remove="ProductGroups\ProductGroupsDataSeedContributor.cs" />
    <Compile Remove="Products\ProductsDataSeedContributorWithDependencies.cs" />
    <Compile Remove="RevenueRepeatFreqs\RevenueRepeatFreqsDataSeedContributor.cs" />
    <Compile Remove="States\StatesDataSeedContributorWithDependencies.cs" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MyProject.Domain\MyProject.Domain.csproj" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="3.0.1" />
    <PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.BackgroundJobs.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.BlobStoring.Database.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.Identity.Pro.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.LanguageManagement.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Saas.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.Abp.TextTemplateManagement.EntityFrameworkCore" Version="4.4.4" />
    <PackageReference Include="Volo.CmsKit.Pro.EntityFrameworkCore" Version="4.4.4" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.*">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
      <PrivateAssets>compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native</PrivateAssets>
    </PackageReference>
  </ItemGroup>

</Project>

如您所見,我正在使用 ABP Commercial 4.4.4 和 EF 5.0。 謝謝你的幫助。

編輯

要求我包含我的數據庫上下文和適用的實體定義。 開始:

MyProductDbContext

[ConnectionStringName("Default")]
public class MyProductDbContext : MyProductDbContextBase<MyProductDbContext>
{
  public MyProductDbContext(DbContextOptions<MyProductDbContext> options)
    : base(options) { }

  public DbSet<Contact> Contacts { get; set; }
  public DbSet<EmailAddress> EmailAddresses { get; set; }
  public DbSet<PhoneNumber> PhoneNumbers { get; set; }
  public DbSet<Department> Departments { get; set; }
  public DbSet<Address> Addresses { get; set; }
  public DbSet<State> States { get; set; }
  public DbSet<Country> Countries { get; set; }

  protected override void OnModelCreating(ModelBuilder builder)
  {
    builder.SetMultiTenancySide(MultiTenancySides.Both);

    base.OnModelCreating(builder);
    if (builder.IsHostDatabase())
    {
      builder.Entity<Country>(b =>
      {
        b.ToTable(MyProductConsts.DbTablePrefix + "Countries", MyProductConsts.DbSchema);
        b.ConfigureByConvention();
        b.Property(x => x.Code).HasColumnName(nameof(Country.Code)).IsRequired()
         .HasMaxLength(CountryConsts.CodeMaxLength);
        b.Property(x => x.Name).HasColumnName(nameof(Country.Name)).IsRequired()
         .HasMaxLength(CountryConsts.NameMaxLength);
        b.Property(x => x.Primary).HasColumnName(nameof(Country.Primary));
        b.Property(x => x.Active).HasColumnName(nameof(Country.Active));
      });
    }

    builder.Entity<State>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "States", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(State.TenantId));
      b.Property(x => x.Code).HasColumnName(nameof(State.Code)).IsRequired().HasMaxLength(StateConsts.CodeMaxLength);
      b.Property(x => x.Name).HasColumnName(nameof(State.Name)).IsRequired().HasMaxLength(StateConsts.NameMaxLength);
      b.Property(x => x.Primary).HasColumnName(nameof(State.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(State.Active));

      // TODO - Implement referential integrity checks in a StateManager domain service
      //b.HasOne<Country>().WithMany().IsRequired().HasForeignKey(x => x.CountryId);
    });
    builder.Entity<Address>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "Addresses", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(Address.TenantId));
      b.Property(x => x.Name).HasColumnName(nameof(Address.Name)).IsRequired()
       .HasMaxLength(AddressConsts.NameMaxLength);
      b.Property(x => x.AddressType).HasColumnName(nameof(Address.AddressType)).IsRequired();
      b.Property(x => x.Line1).HasColumnName(nameof(Address.Line1)).IsRequired()
       .HasMaxLength(AddressConsts.Line1MaxLength);
      b.Property(x => x.Line2).HasColumnName(nameof(Address.Line2)).HasMaxLength(AddressConsts.Line2MaxLength);
      b.Property(x => x.Line3).HasColumnName(nameof(Address.Line3)).HasMaxLength(AddressConsts.Line3MaxLength);
      b.Property(x => x.City).HasColumnName(nameof(Address.City)).IsRequired()
       .HasMaxLength(AddressConsts.CityMaxLength);
      b.Property(x => x.PostalCode).HasColumnName(nameof(Address.PostalCode)).IsRequired()
       .HasMaxLength(AddressConsts.PostalCodeMaxLength);
      b.Property(x => x.Primary).HasColumnName(nameof(Address.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(Address.Active));

      // TODO - Implement referential integrity checks in an AddressManager domain service
      //b.HasOne<State>().WithMany().IsRequired().HasForeignKey(x => x.StateId);
      //b.HasOne<Country>().WithMany().IsRequired().HasForeignKey(x => x.CountryId);
    });
    builder.Entity<Department>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "Departments", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(Department.TenantId));
      b.Property(x => x.Code).HasColumnName(nameof(Department.Code)).HasMaxLength(DepartmentConsts.CodeMaxLength);
      b.Property(x => x.Name).HasColumnName(nameof(Department.Name)).IsRequired()
       .HasMaxLength(DepartmentConsts.NameMaxLength);
      b.Property(x => x.Primary).HasColumnName(nameof(Department.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(Department.Active));
    });
    builder.Entity<EmailAddress>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "EmailAddresses", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(EmailAddress.TenantId));
      b.Property(x => x.Name).HasColumnName(nameof(EmailAddress.Name)).IsRequired()
       .HasMaxLength(EmailAddressConsts.NameMaxLength);
      b.Property(x => x.EmailAddressType).HasColumnName(nameof(EmailAddress.EmailAddressType)).IsRequired();
      b.Property(x => x.Email).HasColumnName(nameof(EmailAddress.Email)).IsRequired()
       .HasMaxLength(EmailAddressConsts.EmailMaxLength);
      b.Property(x => x.Primary).HasColumnName(nameof(EmailAddress.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(EmailAddress.Active));
    });
    builder.Entity<PhoneNumber>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "PhoneNumbers", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(PhoneNumber.TenantId));
      b.Property(x => x.Name).HasColumnName(nameof(PhoneNumber.Name)).IsRequired()
       .HasMaxLength(PhoneNumberConsts.NameMaxLength);
      b.Property(x => x.PhoneNumberType).HasColumnName(nameof(PhoneNumber.PhoneNumberType)).IsRequired();
      b.Property(x => x.Number).HasColumnName(nameof(PhoneNumber.Number)).IsRequired()
       .HasMaxLength(PhoneNumberConsts.NumberMaxLength);
      b.Property(x => x.Primary).HasColumnName(nameof(PhoneNumber.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(PhoneNumber.Active));
      b.Property(x => x.Extension).HasColumnName(nameof(PhoneNumber.Extension))
       .HasMaxLength(PhoneNumberConsts.ExtensionMaxLength);
    });
    builder.Entity<Contact>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "Contacts", MyProductConsts.DbSchema);
      b.ConfigureByConvention();
      b.Property(x => x.TenantId).HasColumnName(nameof(Contact.TenantId));
      b.Property(x => x.Name).HasColumnName(nameof(Contact.Name)).HasMaxLength(ContactConsts.NameMaxLength);
      b.Property(x => x.Surname).HasColumnName(nameof(Contact.Surname)).IsRequired()
       .HasMaxLength(ContactConsts.SurnameMaxLength);
      b.Property(x => x.Title).HasColumnName(nameof(Contact.Title)).HasMaxLength(ContactConsts.TitleMaxLength);
      b.Property(x => x.LastContactDate).HasColumnName(nameof(Contact.LastContactDate))
       .HasMaxLength(ContactConsts.TitleMaxLength);
      b.Property(x => x.Note).HasColumnName(nameof(Contact.Note));
      b.Property(x => x.Primary).HasColumnName(nameof(Contact.Primary));
      b.Property(x => x.Active).HasColumnName(nameof(Contact.Active));

      // many-to-one relationships
      b.HasOne<Department>().WithMany().HasForeignKey(x => x.DepartmentId);
      b.HasOne<Client>().WithMany().HasForeignKey(x => x.ClientId).IsRequired(false);

      // many-to-many relationships
      b.HasMany(x => x.ContactAddresses).WithOne().HasForeignKey(x => x.ContactId).IsRequired();
      b.HasMany(x => x.ContactEmailAddresses).WithOne().HasForeignKey(x => x.ContactId).IsRequired();
      b.HasMany(x => x.ContactPhoneNumbers).WithOne().HasForeignKey(x => x.ContactId).IsRequired();
    });
    builder.Entity<ContactAddress>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "ContactAddresses" + MyProductConsts.DbSchema);
      b.ConfigureByConvention();

      //define composite key
      b.HasKey(x => new { x.ContactId, x.AddressId });

      //many-to-many configuration
      b.HasOne<Contact>().WithMany(x => x.ContactAddresses).HasForeignKey(x => x.ContactId).IsRequired();
      b.HasOne<Address>().WithMany().HasForeignKey(x => x.AddressId).IsRequired();

      b.HasIndex(x => new { x.ContactId, x.AddressId });
    });
    builder.Entity<ContactEmailAddress>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "ContactEmailAddresses" + MyProductConsts.DbSchema);
      b.ConfigureByConvention();

      //define composite key
      b.HasKey(x => new { x.ContactId, x.EmailAddressId });

      //many-to-many configuration
      b.HasOne<Contact>().WithMany(x => x.ContactEmailAddresses).HasForeignKey(x => x.ContactId).IsRequired();
      b.HasOne<EmailAddress>().WithMany().HasForeignKey(x => x.EmailAddressId).IsRequired();

      b.HasIndex(x => new { x.ContactId, x.EmailAddressId });
    });
    builder.Entity<ContactPhoneNumber>(b =>
    {
      b.ToTable(MyProductConsts.DbTablePrefix + "ContactPhoneNumbers" + MyProductConsts.DbSchema);
      b.ConfigureByConvention();

      //define composite key
      b.HasKey(x => new { x.ContactId, x.PhoneNumberId });

      //many-to-many configuration
      b.HasOne<Contact>().WithMany(x => x.ContactPhoneNumbers).HasForeignKey(x => x.ContactId).IsRequired();
      b.HasOne<PhoneNumber>().WithMany().HasForeignKey(x => x.PhoneNumberId).IsRequired();

      b.HasIndex(x => new { x.ContactId, x.PhoneNumberId });
    });
  }
}

接觸

public class Contact : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
  private Contact() { }

  internal Contact(Guid id, string name, [NotNull] string surname, string title,
    DateTime? lastContactDate, string note,
    Guid? departmentId = null, Guid? clientId = null, Guid? tenantId = null,
    bool primary = false, bool active = true)
  {
    Id = id;

    Check.Length(name, nameof(name), ContactConsts.NameMaxLength);
    Check.NotNull(surname, nameof(surname));
    Check.Length(surname, nameof(surname), ContactConsts.SurnameMaxLength);
    Check.Length(title, nameof(title), ContactConsts.TitleMaxLength);

    Name = name;
    Surname = surname;
    Title = title;
    LastContactDate = lastContactDate;
    Note = note;
    Primary = primary;
    Active = active;
    DepartmentId = departmentId;
    ClientId = clientId;
    TenantId = tenantId;
    ContactAddresses = new List<ContactAddress>();
    ContactEmailAddresses = new List<ContactEmailAddress>();
    ContactPhoneNumbers = new List<ContactPhoneNumber>();
  }

  [CanBeNull] public virtual string Name { get; set; }

  [NotNull] public virtual string Surname { get; private set; }

  [CanBeNull] public virtual string Title { get; set; }

  [CanBeNull] public virtual DateTime? LastContactDate { get; set; }

  [CanBeNull] public virtual string Note { get; set; }

  public virtual bool Primary { get; set; }

  public virtual bool Active { get; set; }

  [CanBeNull] public virtual Guid? DepartmentId { get; set; }
  [CanBeNull] public virtual Guid? ClientId { get; set; }

  [NotNull] public virtual ICollection<ContactAddress> ContactAddresses { get; }
  [NotNull] public virtual ICollection<ContactEmailAddress> ContactEmailAddresses { get; }
  [NotNull] public virtual ICollection<ContactPhoneNumber> ContactPhoneNumbers { get; }

  public virtual Guid? TenantId { get; set; }
}

聯系地址

using System;
using Volo.Abp.Domain.Entities;

namespace MyProduct.Contacts;

public class ContactAddress : Entity
{
  private ContactAddress() { }

  public ContactAddress(Guid contactId, Guid addressId)
  {
    ContactId = contactId;
    AddressId = addressId;
  }

  public Guid ContactId { get; protected set; }

  public Guid AddressId { get; protected set; }

  public override object[] GetKeys()
  {
    return new object[] { ContactId, AddressId };
  }
}

ContactEmailAddress 和 ContactPhoneNumber 實體遵循與 ContactAddress 相同的模式。

地址

public class ContactPhoneNumber : Entity
{
  private ContactPhoneNumber() { }

  public ContactPhoneNumber(Guid contactId, Guid phoneNumberId)
  {
    ContactId = contactId;
    PhoneNumberId = phoneNumberId;
  }

  public Guid ContactId { get; protected set; }

  public Guid PhoneNumberId { get; protected set; }

  public override object[] GetKeys()
  {
    return new object[] { ContactId, PhoneNumberId };
  }
}

EmailAddress 和 PhoneNumber 實體遵循與 Address 相同的模式。

我可以提供其他實體,但我認為這些是您需要的。

在處理了查詢語法(我不太熟悉)之后,我使用流利的語法重新編寫了查詢。

  protected virtual async Task<IQueryable<ContactWithNavigationProperties>> GetQueryForNavigationPropertiesAsync()
  {
    var dbContext = await GetDbContextAsync();
    return dbContext.Contacts
                    .Include(c => c.ContactAddresses)
                    .Include(c => c.ContactEmailAddresses)
                    .Include(c => c.ContactPhoneNumbers)
                    .AsSingleQuery()
                    .Select(c => new ContactWithNavigationProperties
                    {
                      Contact = c,
                      Department = dbContext.Departments.FirstOrDefault(d => d.Id == c.DepartmentId),
                      Client = dbContext.Clients.FirstOrDefault(cl => cl.Id == c.ClientId),
                      Addresses = dbContext.Addresses.Where(a =>
                        c.ContactAddresses.Select(ca => ca.AddressId).Contains(a.Id)).ToList(),
                      EmailAddresses = dbContext.EmailAddresses.Where(ea =>
                        c.ContactEmailAddresses.Select(cea => cea.EmailAddressId).Contains(ea.Id)).ToList(),
                      PhoneNumbers = dbContext.PhoneNumbers.Where(pn =>
                        c.ContactPhoneNumbers.Select(cpn => cpn.PhoneNumberId).Contains(pn.Id)).ToList()
                    });
  }

這如我所願。

但是請注意,包含AsSingleQuery()調用。 我收到一個異常,告訴我我的查詢已配置(我想是全局的)使用AsSplitQuery()並且無法使用拆分查詢檢索查詢中的集合。 這是有道理的,因為內部查詢使用包含的依賴項。

我認為我的查詢語法版本發生了同樣的事情,這就是它失敗的原因。

如果您對正在發生的事情或如何修復我的查詢語法有很好的解釋,請發表評論。 希望每個人都能學到一些東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM