在LINQ to Entities中使用自定义方法

时间:2013-11-09 20:50:09

标签: asp.net linq entity-framework

我有一个LINQ表达式:

        var users = db.Relationships.Where(i => i.RelationshipId== relId)
            .Select(s => s.User).Distinct().Select(s => new UserViewModel() {
            Username = s.Username,
            LastActiveDateTime = s.LastActive, // DateTime, I want it to be a string filtered through my custom GetFriendlyDate method
        }).ToList();

        // convert all DateTimes - yuck!
        foreach (var userViewModel in users) {
            userViewModel.LastActive = DateFriendly.GetFriendlyDate(userViewModel.LastActiveDateTime);
        }

此解决方案正常运行,但感觉错误

  • 从数据库中获取后,必须遍历所有users,只需重新格式化每一个属性
  • 在我的ViewModel上有一个DateTime属性,以便稍后可以将其转换为字符串而不再触及

有什么办法可以直接在查询中使用GetFriendlyDate方法吗?

4 个答案:

答案 0 :(得分:2)

可能的解决方案,值得一提:

拥有ViewModel的getter 属性,该属性将返回已转换的字符串,如:

public string LastActive
{
    get
    {
        return DateFriendly.GetFriendlyDate(LastActiveDateTime);        
    }
}

虽然它不能解决现有LastActiveDateTime列的问题,但转换只会在使用时应用(在您的视图中,最有可能 - 无论如何,如果您尝试在查询后的某个地方使用它,它将无法正常工作)已经知道了,所以不需要手动迭代。

创建视图,它将转换服务器端的数据;所以你的数据已经以你需要的格式返回,如果你使用的是DBFirst,可能是最容易和最快的解决方案;

最后,您可以使用ToList()两次,一次之前选择新的ViewModel()(或调用AsEnumerable(),或者找到实现的其他方式查询)。它将从数据库中获取数据,并允许您在ToList()之后直接在查询中执行任何C#侧功能。但是,如前所述 - 它是关于获取所有数据,这些数据符合ToList()的标准 - 在大多数情况下,这不是合适的解决方案。

以下是一些额外的阅读材料:

How can I call local method in Linq to Entities query?

答案 1 :(得分:0)

我在LINQpad中测试了它并且它可以工作。 它仍然有点迭代用户(使用LINQ),但您不必将DateTime属性添加到您的viewmodel类。您还可以使用Automapper将User的集合转换为UserViewModel对象的集合。它当然会迭代用户,但你不会看到它。

当然,因为我没有你的数据库,所以必须创建一些设置代码。

void Main()
{
        var db = new List<User> { 
            new User { LastActive = DateTime.Now, Username = "Adam", Lastname = "Nowak" },
            new User { LastActive = DateTime.Now.AddYears(1), Username = "Eve", Lastname = "Kowalska"}
        };

        // select only properties that you need from database
        var users = db
            .Select(user => new { Username = user.Username, LastActive = user.LastActive})
            .Distinct()
            .ToList();

        var usersVM = from u in users
        select new UserViewModel { Username = u.Username, LastActiveDateTime = DateFriendly.GetFriendlyDate(u.LastActive)};

        usersVM.Dump();
}

        class User
        {
            public DateTime LastActive;
            public string Username;
            public string Lastname;
        };
        class UserViewModel
        {
            public string Username;
            public string LastActiveDateTime;
        }

        static class DateFriendly
        {
            public static string GetFriendlyDate(DateTime date)        
            {
                return "friendly date " + date.Year;
            }
        }

此输出

用户名LastActiveDateTime

亚当友好约会2013

夏娃友好日期2014

答案 2 :(得分:-1)

LINQ没有直接的Concert.ToDate方法。但您可以尝试使用SqlFunctions类中的DateAdd方法:

var users = db.Relationships.Where(i => i.RelationshipId== relId)
    .Select(s => new 
    {
        s.User.Username,
        LastActive=SqlFunctions.DateAdd("d",0, s.LastActive)
    })
    .ToList().Select(s => new UserViewModel()
    {
        Username = s.Username,
        LastActiveDateTime = s.LastActive
    });

答案 3 :(得分:-2)

以下工作不会吗?

var users = db.Relationships.Where(i => i.RelationshipId== relId)
        .Select(s => s.User).Distinct().Select(s => new UserViewModel() {
        Username = s.Username,
        LastActiveDateTime = DateFriendly.GetFriendlyDate(s.LastActive)        
    }).ToList();