Горячий шоколад [UseProjection] + EF Core + PostgreSQL JSONB (через HasConversion >)C#

Место общения программистов C#
Ответить
Anonymous
 Горячий шоколад [UseProjection] + EF Core + PostgreSQL JSONB (через HasConversion >)

Сообщение Anonymous »

Я строю сервер graphQL с хоткоколатом (V15.1), EF Core и NPGSQL, PostgreSQL. У меня есть столбец jsonb , который я отображаю с EF, используя Hasconversion для перечисления . Я хочу сохранить прогнозы и все еще забрать этот JSON в том же SQL. Как только я включил [USEPROCTION] и проецируйте мою сущность в DTO, который содержит эту коллекцию, EF/HC пытается проецировать в список JSON и сбои:

выражение Linq 'X => New attributeValue {key = x.key, value = x.value}. Либо переписать запрос в форме, которая может быть переведена, либо переключиться на оценку клиента, вставив «Asenumerable ' /' tolist '... < /p>
< /blockquote>
minimal repro < /strong> < /p>
entity + ef mapping (-> list через преобразователь):

Код: Выделить всё

public class Product
{
public Guid Id { get; set; }
public string Name { get; set; } = default!;

// jsonb
public List Values { get; set; } = new();
}

public class AttributeValue
{
public string Key { get; set; } = default!;
public string Value { get; set; } = default!;
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var jsonOpts = new JsonSerializerOptions(JsonSerializerDefaults.Web);

modelBuilder.Entity(eb =>
{
eb.Property(e => e.Values)
.IsRequired()
.HasColumnType("jsonb")
.HasConversion(
v => JsonSerializer.Serialize(v, jsonOpts),
v => JsonSerializer.Deserialize[*]>(v, jsonOpts) ?? new())
.Metadata.SetValueComparer(new ValueComparer(
(a,b) => JsonSerializer.Serialize(a, jsonOpts) == JsonSerializer.Serialize(b, jsonOpts),
v => JsonSerializer.Serialize(v, jsonOpts).GetHashCode(),
v => JsonSerializer.Deserialize(JsonSerializer.Serialize(v, jsonOpts), jsonOpts)!));
});
}
< /code>
dto + projection map: < /p>
public class ProductDto
{
public Guid Id { get; set; }
public string Name { get; set; } = default!;

// This is the collection coming from jsonb
public List Values { get; set; } = new();
}

public static class ProductMap
{
public static readonly Expression ToDto =
p => new ProductDto
{
Id           = p.Id,
Name         = p.Name,

// This is the problematic bit:
Values       = p.Values, // jsonb via HasConversion
};
}
< /code>
Resolver: < /p>
[GraphQLName("product")]
[UseFirstOrDefault]   // single result
[UseProjection]       // projections MUST be last
public IQueryable GetProduct(Guid id, [Service] AppDbContext db) =>
db.Products.AsNoTracking()
.Where(p => p.Id == id)
.Select(ProductMap.ToDto);
< /code>
graphql Query: < /p>
{
product(id: "…") {
id
name
values { key value }
}
}

< /code>
error < /p>

выражение Linq 'x => new attributevalue {key = x.key, value = x.value}' Не удалось перевести. Какой EF не может перевести, когда свойство отображается через HasConversion  < /code> < /p>
Что я попробовал: < /p>
[list]
IsProjected(false)
в поле -> Поле полностью упало и в конечном итоге как пустое []
[*] Custom ObjectType + bindfieldsexplicital => new {... values ​​= p.calues}) .Asemerable (). Выберите (x => new Productdto {values ​​= x.values}) -> только работает, если [useProjection] отключена. Есть ли проекционный посетитель врезаться в элементы списка? Есть ли рекомендуемый шаблон, чтобы избежать внутреннего члена для таких свойств?

[*] Если да, то какой наименьший жизнеспособный обходной путь, который сохраняет проекции? />.net 9.0
[*] Горячий шоколад 15.1
[*] ef core 9.0
[/list]
Спасибо за какое -либо шаблон или подтверждение, что это ограничение и что подход x/y.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... nversionli
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»