我正在尝试在一个非常简单的表上运行查询,但我没有得到任何结果。该表包含一个包含以下列的操作日志:
我想得到的是所有EntryID的列表,其中ActionTypeID == 1,Person(department)以动态字符串列表之一结束。问题是应该只检查操作日志中一个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检查第一个条目。
我希望任何人都能理解我想要从困惑的德语翻译成奇怪的英语。
哦 - 顺便说一下,它是.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
在我的示例中,我将搜索日志条目,其中“Person ends with'/ department2'创建了第一次出现的新EntryID”,“TableName =='Contacts'”和“ActionTypeID == 1”。我想要收到的结果是(只有EntryIDs)5,因为这是第一个用户是department2的唯一一个条目用ActionTypeID 1插入这个EntryID。我知道这是愚蠢的,如果我设计了数据库我不会这样做,但现在我必须处理它。如果要查询的部门数量不是动态的,我会使用此代码段:
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(创建)。我甚至不知道为什么应用程序会保存它)
谢谢Ben。
答案 0 :(得分:0)
我认为问题是foreach循环中捕获的变量值(即dep.Value
)。复制变量并在表达式中使用它。该问题已解释为here。
foreach (var dep in b.DepartmentList)
{
var depValue = dep.Value;
predicate = predicate.Or(x => x.Person.EndsWith("/" + depValue));
}
答案 1 :(得分:0)
我决定改用Entity 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();
}
}