I have this model:
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using MyProject.Class.Dto;
namespace SageApi.Model;
public partial class FArticle
{
public string ArRef { get; set; } = null!;
[NotMapped]
public int? Prices { get; set; }
public static void ConfigureModelBuilder(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FArticle>(entity =>
{
entity.HasIndex(e => e.ArRef, "UKA_F_ARTICLE_AR_Ref").IsUnique();
entity.Property(e => e.ArRef)
.HasMaxLength(19)
.IsUnicode(false)
.HasColumnName("AR_Ref");
});
}
}
I'm using HotChocolate Query to get my data with GraphQl:
using SageApi.Model.Sage;
namespace SageApi.Services.GraphQl;
public class Query
{
[UseOffsetPaging(MaxPageSize = 100, IncludeTotalCount = true, DefaultPageSize = 20)]
[UseProjection]
[UseFiltering]
[UseSorting]
public IEnumerable<FArticle> GetFArticles([Service] SageDbContext context) =>
context.FArticles;
}
When I launch my query:
{
fArticles(
skip: 0
take: 1
) {
items {
arRef
prices
}
}
}
It works fine prices
has the value null
.
Now I create a Dto:
namespace SageApi.Class.Dto;
public class PriceDto
{
public short? SomeValue { get; set; }
}
and I change
[NotMapped]
public int? Prices { get; set; }
to
[NotMapped]
public IList<PriceDto>? Prices { get; set; }
Now when I launch the query
{
fArticles(
skip: 0
take: 1
) {
items {
arRef
prices{
someValue
}
}
}
}
I got error:
The LINQ expression 'p1 => new PriceDto{ SomeValue = p1.SomeValue }
' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Why does Dotnet try to get SomeValue
in the database while I clearly specify the [NotMapped]
attribute ? This problem doesn't occur when Prices
is a String
or Int
(not an object).
What am I missing here ?
Also adding NotMapped
to class GrillePriceDto
like so, does not solve the issue:
using System.ComponentModel.DataAnnotations.Schema;
namespace SageApi.Class.Dto;
[NotMapped]
public class PriceDto
{
public short? SomeValue { get; set; }
}
Also adding entity.Ignore(e => e.Prices);
in modelBuilder like so, does not solve the issue:
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using MyProject.Class.Dto;
namespace SageApi.Model;
public partial class FArticle
{
public string ArRef { get; set; } = null!;
[NotMapped]
public IList<PriceDto>? Prices { get; set; }
public static void ConfigureModelBuilder(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FArticle>(entity =>
{
entity.HasIndex(e => e.ArRef, "UKA_F_ARTICLE_AR_Ref").IsUnique();
entity.Property(e => e.ArRef)
.HasMaxLength(19)
.IsUnicode(false)
.HasColumnName("AR_Ref");
entity.Ignore(e => e.Prices);
});
}
}
Minimal reproductible example: https://github.com/Lenny4/NotMappedAttributeListObject
It's not related to EF and based on the Hotchocolate document you need to exclude the property:
Exclude fields: If a projected field is requested, the whole subtree is processed. Sometimes you want to opt out of projections. The projections middleware skips a field in two cases. Either the visitor encounters a field that is a UseProjection field itself, or it defines IsProjected(false).
Link: https://chillicream.com/docs/hotchocolate/v13/fetching-data/projections#exclude-fields
So I could run your app successfully with this config:
public class FArticle
{
public int CbMarq { get; set; }
[IsProjected(true)] public string ArRef { get; set; } = null!;
//Exclude by using: IsProjected(false)
[IsProjected(false)][NotMapped] public IList<PriceDto>? Prices { get; set; }
public static void ConfigureModelBuilder(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FArticle>(entity =>
{
entity.HasKey(e => e.CbMarq).HasName("PK_CBMARQ_F_ARTICLE");
entity.HasIndex(e => e.ArRef, "UKA_F_ARTICLE_AR_Ref").IsUnique();
entity.Property(e => e.ArRef)
.HasMaxLength(19)
.IsUnicode(false)
.HasColumnName("AR_Ref");
entity.Ignore(e => e.Prices);
});
}
}