2012-04-17 62 views
1

我试图在一个非常简单的表上运行查询,但我没有得到任何结果。该表中包含的行为日志有以下栏目:linq动态查询使用PredicateBuilder的实体

  • ID
  • ActionTypeID(创建,编辑或删除)
  • 的EntryID(创建/编辑/或删除条目的ID)
  • 表名(这里的行动是坚定)
  • 控件名称
  • 人(谁犯了行动。NT用户与部门)
  • 日期

我想要得到的是ActionTypeID == 1和Person(department)以动态字符串之一结尾的所有EntryID的列表。问题是,只应检查操作日志中的一个EntryID的第一个操作以匹配其中一个部门。

我知道这听起来很奇怪。这可能是由于我的英语不好,以及我的前同事设计残疾的数据库造成的。我不知道哪个更糟。

我试图得到我想要的结果是这样的:

var predicate = PredicateBuilder.False<ActionLog>(); 
var pOuter = PredicateBuilder.True<ActionLog>(); 

pOuter = pOuter.And(h => h.TableName.ToUpper() == "Contact".ToUpper()); 
pOuter = pOuter.And(h => h.ActionType.ID == 1); 

foreach (var dep in b.DepartmentList) 
{ 
    predicate = predicate.Or(x => x.Person.EndsWith("/" + dep.Value)); 
} 

pOuter = pOuter.And(predicate.Expand()); 

mContactIDs = (from h in db.ActionLog 
orderby h.Date 
select h).AsExpandable().Where(pOuter).Select(x => x.EntryID).Distinct().ToList(); 

但这返回我当“人”与选定的部门结尾的所有条目。我只想用这个EntryID检查第一个条目。

我希望任何人都能理解我想从困惑的德语翻译成奇怪的英语。

OH-顺便说一下,它的.Net 3.5

编辑 我觉得我有一些问题找到合适的解释 - 我会用一些虚拟数据试试。

ID | ActionTypeID | EntryID | TableName | ControlName | Person    | Date 
---------------------------------------------------------------------------------------- 
1 | 1   | 3  | 'Contacts' | NULL  | 'xxxx/department1' | 04/11/2012 
2 | 1   | 3  | 'Contacts' | NULL  | 'yyyy/department2' | 04/11/2012 
3 | 1   | 5  | 'Contacts' | NULL  | 'yyyy/department2' | 04/13/2012 
4 | 1   | 14  | 'Contacts' | NULL  | 'zzzz/department1' | 04/16/2012 

在我的例子,我将搜索与日志条目“人用‘/ department2’结束创建了一个新的EntryID中第一次出现”,“表名==‘联系人’”和“ActionTypeID == 1 ”。我想要接收的结果是(仅限EntryIDs)5,因为这是唯一的入口,其中department2的用户是第一个插入此ActionID的ActionTypeID 1.我知道这很愚蠢,如果我设计了数据库I不会这样做,但现在我必须处理它。如果部门查询的数量不会是动态的,我会用这个片段:

IQueryable<ActionLog> log = db.ActionLog; 
mContactIDs = (from k in db.Contacts 
    where (from h in log 
     where h.TableName == "Contacts" 
     && h.EntryID == k.ID 
     && h.ActionType.ID == 1 
     orderby h.Date 
     select h).FirstOrDefault().Person.EndsWith("/" + b.Department) 
    select k.ID).ToList(); 

但我不知道如何将这些动态部门与愚蠢的设计(和多ActionTypeID 1(创建)连接为一个我甚至不知道为什么应用程序会保存这个)

谢谢,本。

回答

0

我决定改用实体SQL。

 List<int> mContactIDs = new List<int>(); 
     using (var db = new Entities()) 
     { 
      string queryString = @" 
           SELECT 
            VALUE H.EntryID 
           FROM  
            Entities.ActionLog AS H 
           WHERE 
            H.ID IN (
             SELECT VALUE TOP (1) Hi.ID 
             FROM Entities.ActionLog AS Hi 
             WHERE Hi.ActionType.ID = 1 
             AND Hi.TableName = 'Kontakt' 
             AND Hi.EntryID = H.EntryID 
             ORDER BY Hi.Date  
            ) 
           {0} 
           GROUP BY H.EntryID"; 

      List<string> lDepartments = new List<string>(); 
      foreach (var dep in b.DepartmentList) 
      { 
       lDepartments.Add(string.Format(" H.Person LIKE '%{0}' ", dep.Value)); 
      } 

      string sDepartmentQuery = string.Empty; 
      if (lDepartments.Count > 0) 
      { 
       sDepartmentQuery = string.Format(" AND ({0}) ", string.Join(" OR ", lDepartments.ToArray())); 
      } 

      var result = db.CreateQuery<int>(string.Format(queryString, sDepartmentQuery)); 
      if (result != null && result.Count() > 0) 
      { 
       mContactIDs = result.ToList(); 
      } 
     } 
+0

我没有写_that_ :-) – Ben 2012-04-24 12:20:05

0

我认为问题是在foreach循环内捕获的变量值(即dep.Value)。复制变量并在表达式中使用它。该问题解释为here

foreach (var dep in b.DepartmentList) 
{ 
    var depValue = dep.Value; 
    predicate = predicate.Or(x => x.Person.EndsWith("/" + depValue)); 
} 
+0

嗨,谢谢你的回答。这是我没有想到的问题 - 谢谢。但我认为我的主要问题是合乎逻辑的。我想我没有很好地解释它。我会用一些虚拟数据尝试它(我会编辑我的问题) – Ben 2012-04-17 04:31:36