2

我正在尝试在通过 EF 引用表的 LINQ 查询中动态构建 where 子句,但出现以下错误:

'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;
}

更新:添加了 Paul 的建议代码作为试用版。这实际上有效。

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 = "012345678";
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();
4

5 回答 5

8

这是一个使用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 });
}
于 2013-02-15T22:42:43.923 回答
6

我个人非常喜欢使用 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();
于 2013-02-15T20:29:49.323 回答
4

You could/need to use dynamic 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)

Seems to be how it is handled (note the lack of need for string.Format)

于 2013-02-15T19:07:15.840 回答
1

简单的方法是使用LINQExtensionLINQKIT

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();
}
于 2014-03-02T21:37:51.420 回答
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;
            this.@Value = @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

于 2013-05-20T09:17:26.320 回答