使用 Linq for ObjectDataSource:如何使用 ToShortTimeString 转换日期时间?

发布于 2024-07-11 18:26:32 字数 1035 浏览 4 评论 0原文

我正在使用 ObjectDataSource 访问业务类,并尝试生成对用户有意义的输出。 返回值描述一个类(如课堂和教学,而不是软件)。 我想将课程时间显示为这样的范围:“9:00 AM - 10:00 AM”。

这是我用来提取数据的 Linq 查询:

return classQuery.Select(p => new SelectClassData
                              {
                                   ClassID = p.ClassID,
                                   Title = p.Title,
                                   StartDate = p.StartDate.ToShortDateString(),
                                   EndDate = p.EndDate.ToShortDateString(),
                                   TimeOfClass =
                                   p.StartDate.ToShortTimeString() + " - " +
                                                       p.EndDate.ToShortTimeString()
                               }).ToList();

如您所见,我对开始日期和结束日期中的开始时间和结束时间进行编码,即使这些时间可能位于不同的日期。

当我执行此代码时,我得到:

“无法将表达式 'p.EndDate.ToShortTimeString()' 翻译为 SQL,并且无法将其视为本地表达式。”

我知道我正在预测结果但是,作为 Linq 新手,我假设对 ToShortTimeString 的 C# 调用发生在投影之后。 谁能帮我弄清楚如何获得我正在寻找的字符串?

I am accessing a business class using an ObjectDataSource and trying to produce output that makes sense to the user. The return values describe a Class (as in Classroom and teaching, not software). I would like to show the time of the class as a range like this: "9:00 AM - 10:00 AM".

This is the Linq Query I am using to pull the data:

return classQuery.Select(p => new SelectClassData
                              {
                                   ClassID = p.ClassID,
                                   Title = p.Title,
                                   StartDate = p.StartDate.ToShortDateString(),
                                   EndDate = p.EndDate.ToShortDateString(),
                                   TimeOfClass =
                                   p.StartDate.ToShortTimeString() + " - " +
                                                       p.EndDate.ToShortTimeString()
                               }).ToList();

As you can see, I encode the start and ending times in the starting and ending dates even though these could potentially be on different dates.

When I execute this code I get:

"Could not translate expression 'p.EndDate.ToShortTimeString()' into SQL and could not treat it as a local expression."

I know that I am projecting the results but, being new to Linq, I had assumed that the C# call to ToShortTimeString happened after the projection. Can anyone help me figure out how to get the string I'm looking for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青衫儰鉨ミ守葔 2024-07-18 18:26:32

原因是该查询正在 LINQ to SQL 中使用。 LINQ to SQL 将查询视为表达式树。 它为某些方法定义了映射(例如,Contains),但由于它并不真正执行它们,因此它无法在任意方法上工作。 它解析查询并将其提交到 SQL Server。 查询的等效项将作为 SQL 语句在数据库服务器上执行,然后返回结果。 问题是 ToShortTimeString() 在 LINQ to SQL 中没有等效的 SQL 转换。 这里使用的技巧是从 SQL Server 获取数据并调用客户端的方法(AsEnumerable 将执行此操作)。

return classQuery.Select(p => new { p.ClassID, p.Title, p.StartDate, p.EndDate })
   .AsEnumerable()
   .Select(p => new SelectClassData { 
       ClassID = p.ClassID, 
       Title = p.Title, 
       StartDate = p.StartDate.ToShortDateString(), 
       EndDate = p.EndDate.ToShortDateString(), 
       TimeOfClass = p.StartDate.ToShortTimeString() + " - " + p.EndDate.ToShortTimeString() })
   .ToList();

The reason is the query is being used in LINQ to SQL. LINQ to SQL treats queries as expression trees. It has mappings defined for some methods (for instance, Contains) but since it doesn't really execute them, it can't work on arbitrary methods. It parses the query and submits it to SQL server. The equivalent of the query will be executed as a SQL statement on the database server and the result will come back. The problem is ToShortTimeString() does not have an equivalent SQL translation in LINQ to SQL. The trick used here is to fetch data from SQL server and call the method on the client side (AsEnumerable will do this).

return classQuery.Select(p => new { p.ClassID, p.Title, p.StartDate, p.EndDate })
   .AsEnumerable()
   .Select(p => new SelectClassData { 
       ClassID = p.ClassID, 
       Title = p.Title, 
       StartDate = p.StartDate.ToShortDateString(), 
       EndDate = p.EndDate.ToShortDateString(), 
       TimeOfClass = p.StartDate.ToShortTimeString() + " - " + p.EndDate.ToShortTimeString() })
   .ToList();
明月夜 2024-07-18 18:26:32

我非常喜欢迈赫达德的回答。 它不仅解决了问题,还教会了我一些有关 Linq 的知识。 谢谢你!

不过,我一直在努力解决这个问题,并且确实提出了一种不同的方法,我将在这里描述,以防其他人在这个问题上绊倒并想要考虑。 我的 Linq to SQL 代码现在显示为:

return classQuery.Select(p => new SelectClassData
                              {
                                   ClassID = p.ClassID,
                                   Title = p.Title,
                                   sDate = p.StartDate,
                                   eDate = p.EndDate
                              }).ToList();

请注意,sDate 和 eDate 现在是 DateTime 对象而不是字符串。 在“SelectClassData”对象中,我只是更改了声明,以便通过属性 getter 访问 StartDate、EndDate 和 TimeOfClass 变量:

public class SelectClassData
{
    public int ClassID { get; set; }
    public string Title { get; set; }
    public DateTime sDate { get; set; }
    public DateTime eDate { get; set; }
    public string StartDate { get { return GetSDate(); } }
    public string EndDate { get { return GetEDate(); } }
    public string TimeOfClass { get { return GetTimeOfClass(); } }

    protected string GetSDate()
    {
        return sDate.ToShortDateString();
    }

    protected string GetEDate()
    {
        return eDate.ToShortDateString();
    }

    protected string GetTimeOfClass()
    {
        return sDate.ToShortTimeString() + " - " + eDate.ToShortTimeString();
    }
}

也就是说,我通过 LinqToSql 设置 sDate 和 eDate,但执行“ToShortTimeString”和“ToShortDateString”通过在目标数据类中实现 Linq 检索之后进行转换。

I like Mehrdad's answer a lot. It not only solves the problem, it also teaches me something about Linq as well. Thank you!

I've kept banging away at the problem, though, and did come up with a different approach that I'll describe here in case someone else stumbling on this question wants to consider. My Linq to SQL code now reads:

return classQuery.Select(p => new SelectClassData
                              {
                                   ClassID = p.ClassID,
                                   Title = p.Title,
                                   sDate = p.StartDate,
                                   eDate = p.EndDate
                              }).ToList();

Note that sDate and eDate are now DateTime objects instead of strings. In the "SelectClassData" object, I simply changed the declaration so that access to the StartDate, EndDate and TimeOfClass variables go through a property getter:

public class SelectClassData
{
    public int ClassID { get; set; }
    public string Title { get; set; }
    public DateTime sDate { get; set; }
    public DateTime eDate { get; set; }
    public string StartDate { get { return GetSDate(); } }
    public string EndDate { get { return GetEDate(); } }
    public string TimeOfClass { get { return GetTimeOfClass(); } }

    protected string GetSDate()
    {
        return sDate.ToShortDateString();
    }

    protected string GetEDate()
    {
        return eDate.ToShortDateString();
    }

    protected string GetTimeOfClass()
    {
        return sDate.ToShortTimeString() + " - " + eDate.ToShortTimeString();
    }
}

That is, I set the sDate and eDate via the LinqToSql but do the "ToShortTimeString" and "ToShortDateString" transformations after the Linq retrieval by implementing it in the target data class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文