Имею следующую таблицу:
[Table(Schema = "dbo", Name = "Test")]
[Column("Coord.X", MemberName = "Coord.X", CanBeNull = false)]
[Column("Coord.Y", MemberName = "Coord.Y", CanBeNull = false)]
[Column("Coord.Z.Z1", MemberName = "Coord.Z.Z1", CanBeNull = false)]
[Column("Coord.Z.Z2", MemberName = "Coord.Z.Z2", CanBeNull = false)]
public partial class Test
{
[Column, PrimaryKey, Identity]
public long ID;// { get; set; }
public Coord Coord;// { get; set; }
}
Здесь Coord и Z struct-типы нескольких полей
Удалось научиться работать с ними в предикатах:
db.Tests.Where(t => t.Coord != default(Coord))
Однако, когда я пишу их в Selectничего не выходит:
db.Tests.Select(t => t.Coord).Distinct()
Исключение:
Вызвано исключение: "LinqToDB.Linq.LinqException" в linq2db.dll
Необработанное исключение типа "LinqToDB.Linq.LinqException" в linq2db.dll
Expression 't.Coord' is not a Field.
Что и где надо написать, чтобы linq2db понимал такие выражения?
Здравствуйте, Naf2000, Вы писали:
N>Что и где надо написать, чтобы linq2db понимал такие выражения?
Я подозреваю написать(дописать в linq2db) придется довольно много чтобы такое заработало, Danchik поправит если не прав.
Создал feature request
https://github.com/linq2db/linq2db/issues/2874
Здравствуйте, Mace Windu, Вы писали:
MW>Здравствуйте, Naf2000, Вы писали:
N>>Что и где надо написать, чтобы linq2db понимал такие выражения?
MW>Я подозреваю написать(дописать в linq2db) придется довольно много чтобы такое заработало, Danchik поправит если не прав.
MW>Создал feature request https://github.com/linq2db/linq2db/issues/2874
Ну вот с условием не так сложно было сделать:
Expressions.MapBinary((Coord left, Coord right) => left == right, (Coord left, Coord right) => left.X == right.X && left.Y == right.Y && left.Z==right.Z);
Expressions.MapBinary((Coord left, Coord right) => left != right, (Coord left, Coord right) => !(left == right));
Expressions.MapMember((Coord left, Coord right) => left.Equals(right), (Coord left, Coord right) => (left == right));
db.Tests.Where(t => t.Coord != default(Coord))
Здравствуйте, Naf2000, Вы писали:
N>Что и где надо написать, чтобы linq2db понимал такие выражения?
Пока реализовал следующим образом:
namespace DataModels
{
[AttributeUsage(AttributeTargets.Struct)]
public class StructDBTypeAttribute : System.Attribute { }
public static class Queryable
{
public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
var body = UnwrapExpression(selector.Body);
var expression = (Expression<Func<TSource, TResult>>)Expression.Lambda(body, selector.Parameters);
return System.Linq.Queryable.Select<TSource, TResult>(source, expression);
}
private static Expression UnwrapExpression(Expression expression)
{
switch (expression)
{
case NewExpression ex:
return Expression.New(ex.Constructor,
ex.Arguments.Select(arg => UnwrapExpression(arg)),
ex.Members);
case MemberInitExpression ex:
return Expression.MemberInit(ex.NewExpression,
ex.Bindings.Select(b => Expression.Bind(b.Member, UnwrapExpression(((MemberAssignment)b).Expression))));
case MemberExpression ex:
var type = ex.Type;
if(type.GetCustomAttributes(typeof(StructDBTypeAttribute),false).Any())
{
var fields = type.GetFields();
var result = Expression.MemberInit(Expression.New(type), fields.Select(f => Expression.Bind(f, Expression.MakeMemberAccess(ex, f))));
return UnwrapExpression(result);
}
else
{
return ex;
}
default:
return expression;
}
}
}
}
При этом сами структуры должны быть помечены атрибутом
[StructDBType], а полям таблиц БД соответствуют поля структуры (на свойства думаю легко переделать для желающих, но есть момент с инициализацией вложенных структур).
Здравствуйте, Naf2000, Вы писали:
N>Здравствуйте, Naf2000, Вы писали:
N>>Что и где надо написать, чтобы linq2db понимал такие выражения?
[Skip]
N>При этом сами структуры должны быть помечены атрибутом [StructDBType], а полям таблиц БД соответствуют поля структуры (на свойства думаю легко переделать для желающих, но есть момент с инициализацией вложенных структур).
Продумайте лучше API для задания такого поведения, а я уж закачу рукава да и сделаю.
Что-то типа этого
OwnsOne