一对多的双重关系不同的属性同一个类,无法确定导航所代表的关系,C#

问题描述

我想在 Sub PP_Test() Const filename = "C:\Example.pptx" Dim wbk As Workbook,wsh As Worksheet Dim pptApp As PowerPoint.Application,pptPres As PowerPoint.Presentation Set pptApp = new PowerPoint.Application pptApp.Visible = True Set pptPres = pptApp.Presentations.Open(filename) Set wbk = Workbooks("Test.xlsm") 'Loop through the slides and loop through the shapes to find all the Tables. Copy the table,and paste them in Excel Dim s As PowerPoint.Slide,sh As PowerPoint.Shape For Each s In pptPres.Slides For Each sh In s.Shapes 'Create a new sheet in Excel Set wsh = wbk.Worksheets.Add(After:=wbk.Worksheets(wbk.Worksheets.Count)) ' Copy/paste the shape/table sh.Copy wsh.Paste Next sh Next s End Sub 自定义类和 List 自定义类之间使用 NxProperty 建立双重关系。

NxLog

public class NxLog { public string NxLogId { get; set; } public string NxWorkspaceId { get; set; } public string NxConversationId { get; set; } public NxConversation NxConversation { get; set; } public List<NxOutputText> NxOutputTexts { get; set; } public List<NxProperty> RequestProperties { get; set; } //1st Relation public List<NxProperty> ResponseProperties { get; set; } //2nd Relation } public class NxProperty { public string NxPropertyId { get; set; } public string NxWorkspaceId { get; set; } public string NxConversationId { get; set; } public string NxLogId { get; set; } public NxLog NxLog { get; set; } public JToken Value { get; set; } } 女儿班中,我有:

DbContext

但我得到异常:

class CustomDbContext:DbContext
{
    DbSet<NxWorkspace> Workspaces { get; set; }
    DbSet<NxConversation> Conversations { get; set; }
    DbSet<NxLog> Logs { get; set; }
    DbSet<NxOutputText> OutputTexts { get; set; }
    DbSet<NxProperty> RequestProperties { get; set; }
    DbSet<NxProperty> ResponseProperties { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<NxWorkspace>().HasKey(w => w.NxWorkspaceId);
        modelBuilder.Entity<NxConversation>().HasKey(c => new { c.NxWorkspaceId,c.NxConversationId });
        modelBuilder.Entity<NxLog>().HasKey(l => new { l.NxWorkspaceId,l.NxConversationId,l.NxLogId });
        modelBuilder.Entity<NxOutputText>().HasKey(o => new { o.NxWorkspaceId,o.NxConversationId,o.NxLogId,o.NxOutputTextId });
        modelBuilder.Entity<NxProperty>().HasKey(p => new { p.NxWorkspaceId,p.NxConversationId,p.NxLogId,p.NxPropertyId });
        
        modelBuilder.Entity<NxProperty>().Property(l => l.Value)
            .HasConversion<string>(
            o => JsonConvert.SerializeObject(o),d => JsonConvert.DeserializeObject<JToken>(d)
            );
            
        //Other steps
    }
}

我需要确保我拥有正确的代码。

我正在尝试

System.InvalidOperationException: Unable to determine the relationship represented by navigation 'NxLog.RequestProperties' of type 'List<NxProperty>'. Either manually configure the relationship,or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidatePropertyMapping(IModel model,IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model,IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model,IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model,IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
   at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context,IConventionSetBuilder conventionSetBuilder,ModelDependencies modelDependencies)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context,ModelDependencies modelDependencies)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite,RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite,TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite,RuntimeResolverContext context,ServiceProviderEngineScope serviceProviderEngine,RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite,RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite,TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite,TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite,ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType,ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider,Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name,String outputDir,String contextType,String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name,String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to determine the relationship represented by navigation 'NxLog.RequestProperties' of type 'List<NxProperty>'. Either manually configure the relationship,or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
PM>

但我明白...

modelBuilder.Entity<NxLog>()
    .HasMany(l => l.RequestProperties)
    .WithOne(p => p.NxLog).HasForeignKey(p => p.NxLogId);

modelBuilder.Entity<NxLog>()
    .HasMany(l => l.ResponseProperties)
    .WithOne(p => p.NxLog).HasForeignKey(p => p.NxLogId);

我必须如何在 Cannot create a relationship between 'NxLog.ResponseProperties' and 'NxProperty.NxLog' because a relationship already exists between 'NxLog.RequestProperties' and 'NxProperty.NxLog'. Navigation properties can only participate in a single relationship. If you want to override an existing relationship call 'Ignore' on the navigation 'NxProperty.NxLog' first in 'OnModelCreating'. 方法中建立关系?

你能和我分享OnModelCreating(ModelBuilder modelBuilder)的代码吗?

提前致谢

解决方法

我不得不看 9 次才能理解您的代码。所以首先,在我看来,让同一个类代表多个表是错误的。如果您想一起处理它们,请为两者创建一个基类,然后创建子类。这就是您不能正确映射它们的原因,因为名称不明确。但我是来帮忙的。

  1. 步骤:重构您的 NxProperty 类。
  • 使 NxProperty 成为抽象类。
  • 创建一个空类,该类继承自名为 NxRequestProperty 的此类。
  • 创建另一个从该类继承的名为 NxResponseProperty 的空类。

示例:

//NgProperty.cs
public abstract class NxProperty
{
    public string NxPropertyId { get; set; }
    public string NxWorkspaceId { get; set; }
    public string NxConversationId { get; set; }
    public string NxLogId { get; set; }
    public NxLog NxLog { get; set; }
    public JToken Value { get; set; }
}

// NxRequestProperty.cs
// using sealed is just my preference so other
// developers know not to inherit from it without
// asking questions,you can exclude it if you wish.
public sealed class NxRequestProperty : NxProperty {

}

// NxResponseProperty.cs
public sealed class NxResponseProperty : NxProperty {

}
  1. 步骤:重构您的 NxLog 类。使用具体类而不是 NxProperty 抽象类。

示例:

// NxLog.cs
public sealed class NxLog
{
    public string NxLogId { get; set; }
    public string NxWorkspaceId { get; set; }
    public string NxConversationId { get; set; }

    public NxConversation NxConversation { get; set; }

    public List<NxOutputText> NxOutputTexts { get; set; }
    public List<NxRequestProperty> RequestProperties { get; set; }
    public List<NxResponseProperty> ResponseProperties { get; set; }
}
  1. 步骤:重构您的 CustomDbContext。您的 NxProperty 类现在是抽象的,您不应该将它用作 DbSet(恕我直言),让我们重构它。

示例:

// CustomDbContext.cs
public sealed class CustomDbContext : DbContext
{
    DbSet<NxWorkspace> Workspaces { get; set; }
    DbSet<NxConversation> Conversations { get; set; }
    DbSet<NxLog> Logs { get; set; }
    DbSet<NxOutputText> OutputTexts { get; set; }
    // Refactor starts here!
    DbSet<NxRequestProperty> RequestProperties { get; set; }
    DbSet<NxResponseProperty> ResponseProperties { get; set; }
    // Refactor ends here!    

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<NxWorkspace>().HasKey(w => w.NxWorkspaceId);
        modelBuilder.Entity<NxConversation>().HasKey(c => new { c.NxWorkspaceId,c.NxConversationId });
        modelBuilder.Entity<NxLog>().HasKey(l => new { l.NxWorkspaceId,l.NxConversationId,l.NxLogId });
        modelBuilder.Entity<NxOutputText>().HasKey(o => new { o.NxWorkspaceId,o.NxConversationId,o.NxLogId,o.NxOutputTextId });

        // Refactor starts here!
        modelBuilder.Entity<NxRequestProperty>().HasKey(p => new { p.NxWorkspaceId,p.NxConversationId,p.NxLogId,p.NxPropertyId });
        modelBuilder.Entity<NxResponseProperty>().HasKey(p => new { p.NxWorkspaceId,p.NxPropertyId });
        
        modelBuilder.Entity<NxRequestProperty>().Property(l => l.Value)
            .HasConversion<string>(
            o => JsonConvert.SerializeObject(o),d => JsonConvert.DeserializeObject<JToken>(d)
        );
          
        modelBuilder.Entity<NxResponseProperty>().Property(l => l.Value)
            .HasConversion<string>(
            o => JsonConvert.SerializeObject(o),d => JsonConvert.DeserializeObject<JToken>(d)
        );
        // Refactor ends here!
        //Other steps
    }
}
  1. (和最后一步):我不确定 EF Core 现在是否可以映射关系,但我相信始终声明的源代码是更好的源代码,所以这里是如何映射它。由于有复合键,您需要将外键作为所有复合键。

示例:

// CustomDbContext.cs -> inside the OnModelCreating method
modelBuilder.Entity<NxRequestProperty>
    .HasOne(p => p.NxLog)
    .WithMany(l => l.RequestProperties)
    .HasForeignKey(l => new { l.NxWorkspaceId,l.NxLogId });

modelBuilder.Entity<NxResponseProperty>
    .HasOne(p => p.NxLog)
    .WithMany(l => l.ResponseProperties)
    .HasForeignKey(l => new { l.NxWorkspaceId,l.NxLogId });

编辑:

看着我的回答,我意识到将 NxProperty 重构为接口可能更好(并将其称为 INxProperty)。两者都可以,但我认为界面更适合于此。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...