我们有一个使用Linq-To-Sql的程序,并在我们的表上进行了很多类似的查询。特别是,我们有一个timestamp列,我们提取最新的时间戳,以查看自上次查询以来表是否已更改。
System.Data.Linq.Binary ts;
ts = context.Documents
.Select(r => r.m_Timestamp)
.OrderByDescending(r => r)
.FirstOrDefault();
我们经常在与当前表单/查询无关的不同表上重复此查询。我想要做的是创建一个“函数”或可以重复此查询的最后3行的东西(理想情况下可以在每个表上工作)。以下是我想写的内容:
System.Data.Linq.Binary ts;
ts = context.Documents
.GetMostRecentTimestamp();
但我不知道如何创建这个“GetMostRecentTimestamp”。而且,这些查询从未如此简单。它们通常由客户或当前订单过滤,因此更有效的查询可能是
ts = context.Documents
.Where(r => r.CustomerID == ThisCustomerID)
.GetMostRecentTiemstamp();
有任何帮助吗?谢谢!
我选择了Bala R的答案,这里是更新的代码,因此编译:
public static System.Data.Linq.Binary GetMostRecentTimestamp(this IQueryable<Data.Document> docs)
{
return docs
.Select(r => r.m_Timestamp)
.OrderByDescending(r => r)
.FirstOrDefault();
}
此解决方案的唯一缺点是我必须为每个表编写此函数。我会喜欢Tejs的答案,如果它真的有效,但我不会为它重新设计我的数据库。加上DateTime不是一个做时间戳的好方法。
虽然我可以执行诸如Documents.Where(...)。GetMostRecentTimestamp()之类的查询,但如果我尝试执行基于关联的查询(例如MyCustomer.Orders.GetMostRecentTimestamp()或MyCustomer.Orders),此解决方案将失败。.AsQueryable()GetMostRecentTimestamp();
答案 0 :(得分:6)
这实际上很容易做到。您只需要在要为其提供此实体的实体上定义接口:
public class MyEntity : ITimestamp
然后,你的扩展方法:
public static DateTime GetMostRecentTimestamp<T>(this IQueryable<T> queryable)
where T : ITimestamp
{
return queryable.Select(x => x.m_Timestamp)
.OrderByDescending(r => r)
.FirstOrDefault()
}
这对匹配接口的任何实体都很有用:
context.Documents.GetMostRecentTimestamp()
context.SomeOtherEntity.GetMostRecentTimestamp()
答案 1 :(得分:1)
这样的扩展如何
public static DateTime GetMostRecentTimestamp (this IQueryable<Document> docs)
{
return docs.Select(r => r.m_Timestamp)
.OrderByDescending(r => r)
.FirstOrDefault();
}
答案 2 :(得分:1)
嗯...
DateTime timeStamp1 = dataContext.Customers.Max(c => c.TimeStamp);
DateTime timeStamp2 = dataContext.Orders.Max(c => c.TimeStamp);
DateTime timeStamp3 = dataContext.Details.Max(c => c.TimeStamp);
答案 3 :(得分:0)
我创建了一对可以帮助你的扩展方法:ObjectWithMin和ObjectWithMax:
public static T ObjectWithMax<T, TResult>(this IEnumerable<T> elements, Func<T, TResult> projection)
where TResult : IComparable<TResult>
{
if (elements == null) throw new ArgumentNullException("elements", "Sequence is null.");
if (!elements.Any()) throw new ArgumentException("Sequence contains no elements.");
var seed = elements.Select(t => new {Object = t, Projection = projection(t)}).First();
return elements.Aggregate(seed,
(s, x) =>
projection(x).CompareTo(s.Projection) >= 0
? new {Object = x, Projection = projection(x)}
: s
).Object;
}
public static T ObjectWithMin<T, TResult>(this IEnumerable<T> elements, Func<T, TResult> projection)
where TResult : IComparable<TResult>
{
if (elements == null) throw new ArgumentNullException("elements", "Sequence is null.");
if (!elements.Any()) throw new ArgumentException("Sequence contains no elements.");
var seed = elements.Select(t => new {Object = t, Projection = projection(t)}).First();
return elements.Aggregate(seed,
(s, x) =>
projection(x).CompareTo(s.Projection) < 0
? new {Object = x, Projection = projection(x)}
: s
).Object;
}
这两个比OrderBy()更高效。在内存集合中使用FirstOrDefault();但是IQueryable提供商无法解析它们。你可以使用这样的东西:
ts = context.Documents
.Where(r => r.CustomerID == ThisCustomerID)
.ObjectWithMax(r=>r.m_Timestamp);
ts
现在是具有最新时间戳的对象,因此您不需要第二个查询来获取它。