2013-02-15 2 views
1

Я пытаюсь построить где положение динамически в запросе LINQ, который ссылается на таблицы с помощью EF, но я получаю следующее сообщение об ошибке:построение динамического, где положение в LINQ к EF запросы

'ClaimantLastName' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly. Near member access expression, line 6, column 2. 

Вот что я пытаюсь:

string whereClause = string.Format("ClaimantLastName = '{0}' and ClaimantSSN = '{1}'", lastName, ssn); 

Я также пробовал его без одинарных кавычек безрезультатно.

Вот фактический запрос:

return db.Claims.Where(whereClause).Select(
        u => new AdvancedSearchResult 
        { 
         ClaimNumber = u.ClaimNumber, 
. 
. 
. 

Это то, что я пытаюсь сделать это возможно? Кажется, это очень просто. Где я иду не так?

ОБНОВЛЕНИЕ: Вот объект претензии.

public static Claim CreateClaim(global::System.Int32 id, global::System.String claimantFirstName, global::System.String claimantLastName, global::System.String claimantSSN, global::System.DateTime dateOfInjury, global::System.String claimNumber, global::System.String claimantMiddleName, global::System.String claimantAddress1, global::System.String claimantAddress2, global::System.String claimantCity, global::System.String claimantState, global::System.String claimantZip, global::System.DateTime claimantDateOfBirth, global::System.String compensability, global::System.Boolean injuryType, global::System.String jurisdictionState, global::System.String status, global::System.String condition, global::System.String managingBranch, global::System.String bodyPart, global::System.String acceptedBodyPart, global::System.Boolean pGCase, global::System.String employersDefenseAttorney, global::System.String accidentDescription, global::System.String claimExaminerFirstName, global::System.String claimExaminerLastName, global::System.String claimExaminerEmail, global::System.String claimantAttorney, global::System.String workerId, global::System.String workerType) 
{ 
    Claim claim = new Claim(); 
    claim.Id = id; 
    claim.ClaimantFirstName = claimantFirstName; 
    claim.ClaimantLastName = claimantLastName; 
    claim.ClaimantSSN = claimantSSN; 
    claim.DateOfInjury = dateOfInjury; 
    claim.ClaimNumber = claimNumber; 
    claim.ClaimantMiddleName = claimantMiddleName; 
    claim.ClaimantAddress1 = claimantAddress1; 
    claim.ClaimantAddress2 = claimantAddress2; 
    claim.ClaimantCity = claimantCity; 
    claim.ClaimantState = claimantState; 
    claim.ClaimantZip = claimantZip; 
    claim.ClaimantDateOfBirth = claimantDateOfBirth; 
    claim.Compensability = compensability; 
    claim.InjuryType = injuryType; 
    claim.JurisdictionState = jurisdictionState; 
    claim.Status = status; 
    claim.Condition = condition; 
    claim.ManagingBranch = managingBranch; 
    claim.BodyPart = bodyPart; 
    claim.AcceptedBodyPart = acceptedBodyPart; 
    claim.PGCase = pGCase; 
    claim.EmployersDefenseAttorney = employersDefenseAttorney; 
    claim.AccidentDescription = accidentDescription; 
    claim.ClaimExaminerFirstName = claimExaminerFirstName; 
    claim.ClaimExaminerLastName = claimExaminerLastName; 
    claim.ClaimExaminerEmail = claimExaminerEmail; 
    claim.ClaimantAttorney = claimantAttorney; 
    claim.WorkerId = workerId; 
    claim.WorkerType = workerType; 
    return claim; 
} 

UPDATE: предложенный код Added Павла в суде. Это действительно работает.

whereClause = string.Format("ClaimantLastName = \"{0}\" and ClaimantSSN = \"{1}\"", lastName, ssn); 

        List<URIntake.Claim> claims = new List<Claim>(); 
URIntake.Claim claim = new Claim(); 
claim.ClaimantFirstName = "Jay"; 
claim.ClaimantLastName = "Williams"; 
claim.ClaimantSSN = "654219870"; 
claim.ClaimantDateOfBirth = new DateTime(1993, 1, 2); 
claims.Add(claim); 

claim = new Claim(); 
claim.ClaimantFirstName = "Santa"; 
claim.ClaimantLastName = "Claus"; 
claim.ClaimantSSN = ""; 
claim.ClaimantDateOfBirth = new DateTime(1893, 1, 2); 
claims.Add(claim); 

List<AdvancedSearchResult> selectedClaims = claims.AsQueryable().Where(whereClause).Select(
    u => new AdvancedSearchResult 
    { 
     ClaimNumber = u.ClaimNumber, 
     DateOfBirth = u.ClaimantDateOfBirth, 
     DateOfInjury = u.DateOfInjury, 
     Denied = u.Compensability == "Denied" 
    }).ToList(); 
+0

Пожалуйста, добавьте изображение 'db.Объект Claims' –

ответ

2

Можно/нужно использовать динамические Linq

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

db.Where("Something = @0 And SomethingElse = @1", "Blah", 42)

, кажется, как он обрабатывается (обратите внимание на отсутствие необходимости string.Format)

+0

Добавление этой библиотеки и «использование System.Linq.Dynamic», похоже, не имеет значения. Все еще получаю мое оригинальное исключение, хотя предложение where, похожее на то, что в статье. – birdus

+0

Вам не нужно делать string.Format. см. update –

+0

Если я так делаю, как я могу построить динамическое предложение where? То, как вы показываете (о котором я читал ранее), мне придется создать полдюжины полных операторов LINQ (так как у меня есть полдюжины совершенно разных, где клаузулы), устраняя любую потребность в динамическом создании предложения where. Может быть, я что-то упустил. – birdus

5

Мне лично очень нравится использовать PredicateBuilder, потому что у него все еще есть внешний вид LINQ, а не какая-то волшебная строка. Вы можете иметь всевозможные условия, а затем добавить предложение к этому предикату, и он скомпилирует все красивое и чистое для вас.

http://www.albahari.com/nutshell/predicatebuilder.aspx

Вот разрезали образец из моего кода:

var predicate = PredicateBuilder.True<MarketingCabinetItem>(); 

//add vendor filter 
if (vendorComboBox.SelectedValue != null && !String.IsNullOrEmpty(vendorComboBox.SelectedValue.ToString())) 
{ 
    var vend = vendorComboBox.SelectedValue.ToString(); 
    predicate = predicate.And(m => m.Vendor == vend); 
    vendPredicate.And(v => v.VendorName == vend); 
} 


//get all mkt item types in category 
if (categoryComboBox.SelectedValue != null) 
{ 
    var mktCatId = Guid.Parse(categoryComboBox.SelectedValue.ToString()); 
    predicate = predicate.And(p => p.CategoryCategoryId == mktCatId); 
} 

// get the marketing items using the inner and outer 
var mktItems = (from mi in ctx.MarketingItem.AsExpandable() 
       join mType in ctx.ItemType.AsExpandable() on mi.MarketingItemTypeId equals mType.Id 
       join mktCat in ctx.Category.AsExpandable() on mType.MarketingItemCategoryId equals mktCat.Id 
       join att in ctx.Attachment.AsExpandable() on mi.Id equals att.MarketingItemId 
       join pri in ctx.Priority.AsExpandable() on mi.PriorityId equals pri.Id 


       select new MarketingCabinetItem 
       { 
        Id = mi.Id, 
        Title = mi.Title, 
        ItemTypeDescription = mType.Description, 
        PriorityLevel = pri.Level, 
        StartDate = mi.StartDate, 
        ExpirationDate = mi.ExpirationDate, 
        HasAttachments = att != null, 
        CategoryDescription = mktCat.Description 
       }).Where(predicate).ToList(); 
+0

Huh. Я видел подобные вещи раньше в других ORM, но мне не приходило в голову попробуйте в этом примере.Я посмотрю на это.Спасибо! – birdus

+0

Похоже, что это не будет работать с LINQ to Entities. Я получаю это сообщение об ошибке: «Тип узла выражения LINQ« Invoke »не поддерживается в LINQ to Entities . " – birdus

+0

Вы добавили .AsExpandable(), потому что LINQKit поддерживает LINQ для Entities, так как фрагмент кода, который я опубликовал, был LINQ to Entities – Charles380

4

Вот пример использования System.Linq.Expressions. Хотя пример здесь специфичен для вашего класса Claim, вы можете создавать такие функции, как этот общий, а затем использовать их для динамического создания предикатов для всех ваших объектов. Я использую недавно, чтобы предоставить пользователям гибкий поиск объектов в любой функции объекта (или групп свойств) без необходимости жесткого кодирования всех запросов.

public Expression<Func<Claim, Boolean>> GetClaimWherePredicate(String name, String ssn) 
{ 
    //the 'IN' parameter for expression ie claim=> condition 
    ParameterExpression pe = Expression.Parameter(typeof(Claim), "Claim"); 

    //Expression for accessing last name property 
    Expression eLastName = Expression.Property(pe, "ClaimantLastName"); 

    //Expression for accessing ssn property 
    Expression eSsn = Expression.Property(pe, "ClaimantSSN"); 

    //the name constant to match 
    Expression cName = Expression.Constant(name); 

    //the ssn constant to match 
    Expression cSsn = Expression.Constant(ssn); 

    //the first expression: ClaimantLastName = ? 
    Expression e1 = Expression.Equal(eLastName, cName); 

    //the second expression: ClaimantSSN = ? 
    Expression e2 = Expression.Equal(eSsn, cSsn); 

    //combine them with and 
    Expression combined = Expression.And(e1, e2); 

    //create and return the predicate 
    return Expression.Lambda<Func<Claim, Boolean>>(combined, new ParameterExpression[] { pe }); 
} 
1
public class SearchField 
    { 
     public string Name { get; set; } 
     public string @Value { get; set; } 
     //public string Operator { get; set; } 

     public SearchField(string Name, string @Value) 
     { 
      this.Name = Name; 
      [email protected] = @Value; 
      //Operator = "="; 
     } 
    } 

    public class FilterLinq<T> 
    { 
     public static Expression<Func<T, Boolean>> GetWherePredicate(params SearchField[] SearchFieldList) 
     { 

      //the 'IN' parameter for expression ie T=> condition 
      ParameterExpression pe = Expression.Parameter(typeof(T), typeof(T).Name); 

      //combine them with and 1=1 Like no expression 
      Expression combined = null; 

      if (SearchFieldList != null) 
      { 
       foreach (var fieldItem in SearchFieldList) 
       { 
        //Expression for accessing Fields name property 
        Expression columnNameProperty = Expression.Property(pe, fieldItem.Name); 


        //the name constant to match 
        Expression columnValue = Expression.Constant(fieldItem.Value); 

        //the first expression: PatientantLastName = ? 
        Expression e1 = Expression.Equal(columnNameProperty, columnValue); 

        if (combined == null) 
        { 
         combined = e1; 
        } 
        else 
        { 
         combined = Expression.And(combined, e1); 
        } 
       } 
      } 

      //create and return the predicate 
      return Expression.Lambda<Func<T, Boolean>>(combined, new ParameterExpression[] { pe }); 
     } 

    } 

И вы можете назвать это для любого класса

ClinicEntities x = new ClinicEntities(); 

    dataGridView1.DataSource = x.Patient 
          .Where(
FilterLinq<Patient>.GetWherePredicate(
new SearchField("PatientNameEnglish", "Mona Mohamed Ali"), 
new SearchField("PatientHusbandName", "Ahmed Sallam Kareem"))).ToList(); 

Наконец Спасибо за bmused

0

простой способ заключается в использовании LINQExtension с LINQKIT

using (var context = new workEntities()) 
{ 

    Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); 
    dictionary["Title"] = new List<string> { 
        "Network Engineer", 
        "Security Specialist", 
        "=Web Developer" 
       }; 
    dictionary["Salary"] = new List<string> { ">=2000" }; 
    dictionary["VacationHours"] = new List<string> { ">21" }; 
    dictionary["SickLeaveHours"] = new List<string> { "<5" };     
    dictionary["HireDate"] = new List<string> { 
        ">=01/01/2000", 
        "28/02/2014" 
       }; 
    dictionary["ModifiedDate"] = new List<string> { DateTime.Now.ToString() }; 

    var data = context.Employee.CollectionToQuery(dictionary).ToList(); 
} 
Смежные вопросы