簡體   English   中英

如何在 OData 和 DotnetCore 中擴展繼承的實體屬性?

[英]How to expand inherited entities properties in OData and DotnetCore?

我在 Dotnet core 2.2.0 和 OData 7.2.1 中實現了以下實體。

模塊.cs:

using System.Collections.Generic;
namespace Models
{
    public abstract class Module
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public virtual ICollection<ModuleDefinition> ModuleDefinitions { get; set; }
    }
}

發票.cs:

namespace Models
{
    public class Invoice : Module
    {

    }
}

模塊定義:

namespace Models
{
    public class ModuleDefinition
    {
        public int ModuleId { get; set; }
        public Module Module { get; set; }
        public int DefinitionId { get; set; }
        public Definition Definition { get; set; }
    }
}

定義.cs

using System.Collections.Generic;
namespace Models
{
    public class Definition
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public virtual ICollection<ModuleDefinition> ModuleDefinitions { get; set; }
    }
}

上下文.cs:

using Microsoft.EntityFrameworkCore;

namespace Models
{
    public class Context : DbContext
    {
        public Context(DbContextOptions<Context> options) : base(options) { }

        public DbSet<Module> Modules { get; set; }
        public DbSet<Invoice> Invoices { get; set; }
        public DbSet<Definition> Definitions { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ModuleDefinition>()
                        .HasKey(md => new { md.ModuleId, md.DefinitionId });
            modelBuilder.Entity<ModuleDefinition>()
                        .HasOne(md => md.Module)
                        .WithMany(m => m.ModuleDefinitions)
                        .HasForeignKey(md => md.ModuleId);
            modelBuilder.Entity<ModuleDefinition>()
                        .HasOne(md => md.Definition)
                        .WithMany(d => d.ModuleDefinitions)
                        .HasForeignKey(md => md.DefinitionId);
        }
    }
}

啟動.cs:

var builder = new ODataConventionModelBuilder();
            builder.EntitySet<Invoice>("Invoices");
            builder.EntitySet<Module>("Modules");
            builder.EntitySet<ModuleDefinition>("ModuleDefinitions").EntityType.HasKey(t => new { t.ModuleId, t.DefinitionId }); ;
            builder.EnableLowerCamelCase();
            app.UseOData(routeName: "ODataRoute", routePrefix: "odata", model: builder.GetEdmModel());

調用這個 url https://localhost:5001/odata/modules?$expand=moduleDefinitions是可以的,我得到了這個響應:

{"@odata.context":"https://localhost:5001/odata/$metadata#Modules(moduleDefinitions())","value":[{"@odata.type":"#Models.Invoice","id":1,"title":"t","description":"d","moduleDefinitions":[{"moduleId":1,"definitionId":1}]}]}

但是當嘗試通過 OData 擴展 Invoice Entity 的 ModuleDefinition 時: https://localhost:5001/odata/invoices?$expand=moduleDefinitions我期望是這樣的:

{"@odata.context":"https://localhost:5001/odata/$metadata#Invoice(moduleDefinitions(definition()))","value":[{"@odata.type":"#Models.Invoice","id":1,"title":"t","description":"d","test":"","moduleDefinitions":[{"moduleId":1,"definitionId":1,"definition":{"id":1,"name":"n"}}]}]}

但我在 dotnet 中遇到錯誤:

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT [m].[Id], [m].[Description], [m].[Discriminator], [m].[Title], [m].[test]
      FROM [Modules] AS [m]
      WHERE [m].[Discriminator] = N'Invoice'
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'Models.Context'.
      System.ArgumentNullException: Value cannot be null.
      Parameter name: source
         at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
         at lambda_method(Closure , QueryContext , Invoice )
         at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
         at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper<TOut>.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
         at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext()
         at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
   at lambda_method(Closure , QueryContext , Invoice )
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper<TOut>.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()

問題是什么?

我根據Jerther 的回答解決了這個問題

我剛剛編輯了Startup.cs:

var builder = new ODataConventionModelBuilder();
            builder.EntitySet<Invoice>("Invoices").EntityType.DerivesFromNothing(); //Edited Code
            builder.EntitySet<Module>("Modules");
            builder.EntitySet<ModuleDefinition>("ModuleDefinitions").EntityType.HasKey(t => new { t.ModuleId, t.DefinitionId }); ;
            builder.EnableLowerCamelCase();
            app.UseOData(routeName: "ODataRoute", routePrefix: "odata", model: builder.GetEdmModel());

暫無
暫無

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

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