Динамический запрос Linq на связь с внешним ключом типа Guid

Я использую System.Linq.Dynamic для динамического запроса к источнику данных IQueryable с использованием предложения where в строковом формате. , так:

var result = source.Entities.Where("City = @0", new object[] { "London" });

Пример выше работает нормально. Но теперь я хочу запросить свойство внешнего ключа типа Guid следующим образом:

var result = source.Entities.Where("CompanyId = @0", new object[] { "838AD581-CEAB-4B44-850F-D05AB3D791AB" });

Это не сработает, потому что по умолчанию Guid нельзя сравнивать со строкой. И я должен предоставить guid в виде строки, потому что он изначально исходит из json-запроса, а json не поддерживает guid.

Во-первых, это вообще правильный способ запроса отношений или для этого есть другой синтаксис?

Во-вторых, как изменить Dynamic.cs из проекта Dynamic Linq для автоматического преобразования строки в guid, если сравниваемое свойство объекта имеет тип guid?


person Andreas Zita    schedule 08.02.2014    source источник
comment
почему вы передаете строку в качестве параметра вместо Guid? попробуйте использовать Guid.Parse и передать guid   -  person Grundy    schedule 08.02.2014
comment
Как я уже писал, запрос исходит из json-запроса, и я не могу выполнить преобразование возможных строк guid в guids. Было бы лучше, если бы Dynamic.cs можно было изменить, чтобы обнаруживать, когда я пытаюсь сравнить Guid со строкой, и вместо этого выполнять преобразование.   -  person Andreas Zita    schedule 08.02.2014


Ответы (1)


У вас есть много способов решения. Проще всего, как я думаю, будет изменить ваш запрос следующим образом

var result = source.Entities.Where("CompanyId.Equals(@0)", new object[] { Guid.Parse("838AD581-CEAB-4B44-850F-D05AB3D791AB") });

Если вы хотите использовать операторы = и ==, то в Dynamic.cs вам нужно изменить interface IEqualitySignatures : IRelationalSignatures вот так

interface IEqualitySignatures : IRelationalSignatures
{
    ....
    F(Guid x, Guid y);
    ....
}

после этого вы можете использовать следующий запрос

var result = source.Entities.Where("CompanyId=@0", new object[] { Guid.Parse("838AD581-CEAB-4B44-850F-D05AB3D791AB") });

OR

var result = source.Entities.Where("CompanyId==@0", new object[] { Guid.Parse("838AD581-CEAB-4B44-850F-D05AB3D791AB") });

Но если вы хотите использовать параметр string, вам нужно изменить метод ParseComparison в классе ExpressionParser. Вам нужно добавить еще одну проверку типов операндов, подобных этому

....
//you need add this condition
else if(left.Type==typeof(Guid) && right.Type==typeof(string)){
    right = Expression.Call(typeof(Guid).GetMethod("Parse"), right);
}
//end condition
else {
    CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), op.text, ref left, ref right, op.pos);
}
....

и тогда ваш запрос будет работать

var result = source.Entities.Where("CompanyId = @0", new object[] { "838AD581-CEAB-4B44-850F-D05AB3D791AB" });
person Grundy    schedule 08.02.2014