none
请教一个LINQ to Entities 代码的写法 RRS feed

  • 问题

  • 我有一个用户可以发送消息的系统,一个用户可以跟随多个用户,以查看这些用户发送的消息。
    我设计了三个表,Users 、Statuses(消息表)、Followers (跟随表, 此表有两个字段,UserId和FollowerId,全部与Users的主键对应)

    我生成的edmx里有 Users 和 Statues 两个实体。


    请教:获取某用户A,的所有更随者已经发过的消息的 LINQ to Entities 代码如何写?

    我想LINQ to Entities 代码最终得到类似这样的t-sql语句:
    WITH AllFollowers (FollowerId) AS
    (
    SELECT     f.FollowerId
    FROM         Followers AS f INNER JOIN
                          TwitterUsers AS ff ON f.FollowerId = ff.Id
    WHERE     (f.UserId = 1) -- 这里的1实际应用中为参数
    )
    SELECT     s.CreatedAt, s.Id, s.UserId, s.[Text]
    FROM Statuses AS s
    INNER JOIN AllFollowers f on s.UserId = f.FollowerId
    或者
    SELECT     s.CreatedAt, s.Id, s.UserId, s.[Text]
    FROM Statuses AS s
    INNER JOIN
    (
    SELECT     f.FollowerId
    FROM         Followers AS f INNER JOIN
                          TwitterUsers AS ff ON f.FollowerId = ff.Id
    WHERE     (f.UserId = 1) -- 这里的1实际应用中为参数
    ) AS tt on tt.FollowerId = s.UserId


    2009年8月3日 1:25

答案

全部回复

  • from user in User
    from Follower in User.Followers
    where User.Userid==1;
    select Follower.Statues

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月3日 3:23
    版主
  • 非常感谢老大,这样写成功了
    var status = from user in edm.Users
                                 from f in user.FollowTo
                                 where user.Id == 1
                                 select f.Statuses;

    但,我如何再进一步添加分页功能呢? 要先按f.Statuses.CreateAt属性排序,然后Skip,及Take,但f.Statuses是EntityCollection类型,怎样才能按照Statuses的CreateAt属性排序呢?
    2009年8月3日 4:33
  • status=status.OrderBy(Status=>Status.CreateAt);

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月3日 5:04
    版主
  • 再次感谢。
    var q = status.OrderBy(s => s.CreateAt) ;// 我这样写提示s 为EntityCollection<Status>类型,而不是Status,所以这样写并不正确。
    2009年8月3日 5:09
  • var status = from user in edm.Users
                                 from f in user.FollowTo
    from s in f.Statuses
                                 where user.Id == 1
                                 select s;

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月3日 5:12
    版主
  • 噢,等我再试一下,非常感谢

    2009年8月3日 5:13
  • 查询是没问题了,但又有新问题了:Statuses里有导航属性Users,为了省事,我表示层也是用Statuses作为表示层实体,同时数据访问层也用Statuses传输数据,这样我需要Statuses有个Username属性,方便界面的显示。所以我将上面的LINQ to Entities 查询改成了这样:
    var status = from u in edm.TwitterUsers
                                 from f in u.FollowTo
                                 from s in f.Statuses
                                 where u.Id == 1
                                 select new Statuses
                                 {
                                     CreatedAt = s.CreatedAt,
                                     Favorited = s.Favorited,
                                     Id = s.Id,
                                     InReplyToScreenName = s.InReplyToScreenName,
                                     InReplyToStatusID = s.InReplyToStatusID,
                                     InReplyToUserID = s.InReplyToUserID,
                                     Source = s.Source,
                                     Text = s.Text,
                                     Truncated = s.Truncated,
                                     //UserId = u.Id.ToString(),
                                     Username = u.Name// 我估计问题出在这里,LINQ to Entities 查询是不是不支持MSL之外的EntitySet属性,估计SQL语句是根据SSDL生产的吧?
                                 };
    会出现这个问题:
    在 LINQ to Entities 查询中无法构造实体或复杂类型“XXXModel.Statuses”。


    当然,
    var status = from u in edm.TwitterUsers
                                 from f in u.FollowTo
                                 from s in f.Statuses
                                 where u.Id == 1
                                 select s;
    这个LINQ to Entities 查询没有问题。
    2009年8月3日 5:33
  • 我这里还有这个问题:如何简化Linq 语句中的select new {......}
    http://social.microsoft.com/Forums/zh-CN/adonetzhchs/thread/76f2c3bb-3020-433e-b3ec-289015adfe11

    我估计 直接这样写:
    var status2 = from s in edm.Statuses
                  where s.Users.Id == userId
                  join u in edm.Users on s.Users.Id equals u.Id
                  select new
                  {
                      CreatedAt = s.CreatedAt,
                      Favorited = s.Favorited,
                      Id = s.Id,
                      InReplyToScreenName = s.InReplyToScreenName,
                      InReplyToStatusID = s.InReplyToStatusID,
                      InReplyToUserID = s.InReplyToUserID,
                      Source = s.Source,
                      Text = s.Text,
                      Truncated = s.Truncated,
                      UserId = u.Id,
                      Username = u.Name
                  };
    也会报这个错:“在 LINQ to Entities 查询中无法构造实体或复杂类型“XXXModel.Statuses”。”
    我马上试试。
    2009年8月3日 5:39
  • var status = from u in edm.Users
                                 from f in u.FollowTo
                                 from s in f.Statuses
                                 where u.Id == 1
                                 //////join user in edm.Users on s.Users.Id equals user.Id
                                 select new
                                 {
                                     CreatedAt = s.CreatedAt,
                                     Favorited = s.Favorited,
                                     Id = s.Id,
                                     InReplyToScreenName = s.InReplyToScreenName,
                                     InReplyToStatusID = s.InReplyToStatusID,
                                     InReplyToUserID = s.InReplyToUserID,
                                     Source = s.Source,
                                     Text = s.Text,
                                     Truncated = s.Truncated,
                                     UserId = u.Id,
                                     Username = u.Name
                                 };

    我这样试了一下,查询是通过了,但得到结果不正确,Username和UserId  全是一个值,就是where条件的1,Username的值应该是用户1所跟随的人, 显然生成的sql语句不是我想要的,
    2009年8月4日 3:00
  • 我觉得结果不对的原因在于:
    from u in edm.Users
    from f in u.FollowTo

    这两句其实有个约束,即 u.Id == f.UserId,我如何加这个约束条件呢?但f不可能有UserId属性,这里是不是要将Followers表(跟随表, 此表有两个字段,UserId和FollowerId),也引进来?

    这个嵌套查询中SELECT     f.FollowerId,不知如何能得到,
    SELECT     s.CreatedAt, s.Id, s.UserId, s.[Text]
    FROM Statuses AS s
    INNER JOIN
    (
    SELECT     f.FollowerId
    FROM         Followers AS f INNER JOIN
                          TwitterUsers AS ff ON f.FollowerId = ff.Id
    WHERE     (f.UserId = 1) -- 这里的1实际应用中为参数
    ) AS tt on tt.FollowerId = s.UserId
    2009年8月5日 1:23
  • 一方面是,太不了解EF了,在一个就是EF使用起来很不习惯,估计要等 EF v3才能使用起来习惯,呵呵
    2009年8月5日 1:27
  • 直接用Status不就可以了?如果要获取关联的User的Name属性可以通过status.User.Name来获取~在使用这个语句获取之前可能需要先status.UserReference.Load()
    宠辱不惊,看庭前花开花落。去留无意,望天上云卷云舒。
    2009年8月5日 1:33
    版主
  • 这个查询得到的UserName应该是id=1的User的Name吧~
    宠辱不惊,看庭前花开花落。去留无意,望天上云卷云舒。
    2009年8月5日 1:35
    版主
  • 这个查询得到的UserName应该是id=1的User的Name吧~
    ====================
    确实
    2009年8月5日 4:58
  • 直接用Status不就可以了?
    +=======
    请教,直接用Status 怎样用法?
    2009年8月5日 5:00
  • status.User.Name
    宠辱不惊,看庭前花开花落。去留无意,望天上云卷云舒。
    2009年8月5日 5:17
    版主
  • 非常感谢

    2009年8月6日 0:41