Как использовать переменную с моим предложением WHERE в моем запросе Entity Framework - PullRequest
0 голосов
/ 16 мая 2019

Я выполняю запрос в своем проекте с несколькими объединениями.Я хочу снабдить предложение WHERE переменной, а не жестко закодированной, как сейчас, но, похоже, не могу получить правильный синтаксис.

var data = (from a in db.StudentData
            join b in db.Contacts on a.SID equals b.SID
            join c in db.Addresses on a.SID equals c.SID
            join d in db.EntryQuals.DefaultIfEmpty() on a.SID equals d.SID                            
            where a.SID == searchTxt
                  select new
                    {
                        ID = a.SID,
                        Birthdate = a.BIRTHDTE,
                        FirstName = a.FNAMES,
                        PreviousName = a.PREVSURNAME,                                
                        EntryQualAwardID = d.ENTRYQUALAWARDID,
                        AwardDate = d.AWARDDATE
       }).ToList();

Как мне заставить мое предложение WHERE работать с переменной (т. Е.: a. [fieldVar]) где fieldVar может быть «SID» в том виде, в каком оно находится в коде в настоящее время.

Ответы [ 2 ]

1 голос
/ 17 мая 2019

При работе с выбираемыми пользователем критериями поиска вам нужно будет указать возможные варианты выбора.При работе со строками поиска я рекомендую использовать синтаксис Fluent вместо синтаксиса Linq QL, поскольку он создает выражение, которое можно условно изменить по ходу работы.Оттуда вы можете использовать Predicate & PredicateBuilder для динамического составления условия WHERE.

Решение Жака будет работать, но недостатком этого подхода является то, что вы создаете довольно большой и сложный оператор SQL, который условно применяет критерии.Я предпочитаю условно добавлять в код предложения WHERE, чтобы SQL был настолько сложным, насколько это необходимо.

Если вы хотите сделать что-то вроде интеллектуального поиска (представьте, что Google с одной текстовой записьюпоиск по нескольким возможным полям)

var whereClause = PredicateBuilder.False<StudentData>();
int id;
DateTime date;
if(int.TryParse(searchTxt, out id))
    whereClause = whereClause.Or(x => x.SID == id);
else if(DateTime.TryParse(searchTxt, out date))
    whereClause = whereClause.Or(x => x.BirthDate == date);
else
   whereClause = whereClause.Or(x => x.FirstName.Contains(searchTxt));

var data = db.StudentData
    .Where(whereClause)
    .Select(a => new
    {
        ID = a.SID,
        Birthdate = a.BIRTHDTE,
        FirstName = a.FNAMES,
        PreviousName = a.PREVSURNAME,                                
        EntryQualAwardID = a.EntryQuals.ENTRYQUALAWARDID,
        AwardDate = a.EntryQuals.AWARDDATE
    }).ToList();

Это выполняет некоторые базовые оценки критериев поиска, чтобы определить, соответствует ли он цели поиска.Т.е. если они могут выполнять поиск по имени, дате или идентификатору, а идентификаторы являются числовыми, мы будем искать только по идентификатору, если критерии были числовыми.Если это выглядит как дата, мы ищем по дате, в противном случае мы ищем по имени.(и, возможно, другие доступные для поиска строки)

Если они могут искать ID, FirstName и BirthDate и ввести одно или несколько из них в качестве отдельных полей ввода (страница критериев поиска), то в зависимости от того, какие записи они заполняют, вы можетелибо передайте отдельные обнуляемые параметры и выполните вышеизложенное в зависимости от того, какие параметры передаются, или передайте список значений поиска с чем-то вроде Enum, для которого искали значение:

Т.е. по параметрам:

private void ByParameters(int? id = null, DateTime? birthDate = null, string name = null)
{
    var whereClause = PredicateBuilder.False<StudentData>();
    if(id.HasValue)
        whereClause = whereClause.Or(x => x.SID == id.Value);
    if(date.HasValue)
    {
        DateTime dateValue = date.Value.Date;   
        whereClause = whereClause.Or(x => x.BirthDate == dateValue);
    }
    if (!string.IsNullOrEmpty(name))
       whereClause = whereClause.Or(x => x.FirstName.Contains(name));

    // ....
}

Если число параметров начинает становиться большим, то может быть создан пользовательский тип для инкапсуляции отдельных значений NULL.Т.е.:

[Serializable]
public class SearchCriteria
{
    public int? Id { get; set; }
    public DateTime? BirthDate { get; set; }
    public string Name { get; set; }
}
private void ByParameters(SearchCriteria criteria)
{
    // ....
}

Или вы можете составить более динамический объект списка параметров с типом и значением критерия, но он начинает становиться более сложным, чем это, вероятно, стоит.

0 голосов
/ 16 мая 2019

Вы не можете сделать это в Linq, sine linq должен знать тип поля во время компиляции.Обходной путь может быть что-то вроде

where (fieldVar=="SID" && a.SID == searchTxt) || 
      (fieldVar=="FNAMES" && a.FNAMES== searchTxt) || ...

Это также предупредит вас во время компиляции, если вы делаете недопустимое сравнение, например.сравнение даты со строкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...