5

我有一個使用實體框架來獲取數據的ASP.NET MVC應用程序。如何重用實體框架中的投影?

我需要傳遞他們查看之前的entites轉化爲模型。預測可能非常複雜,但爲了保持簡單:

public static IQueryable<UserModel> ToModel(this IQueryable<User> users) 
{ 
    return from user in users 
      select new UserModel 
      { 
       Name = user.Name, 
       Email = user.Email, 
      }; 
} 

這可以在控制器中使用這樣的:

return View(Repository.Users.ToModel().ToList()); 

非常好。但是如果我想在另一個裏面使用這個投影呢?例如:

public static IQueryable<BlogPostModel> ToModel(this IQueryable<BlogPost> blogs) 
{ 
    return from blogs in blogs 
      select new BlogPostModel 
      { 
       Title = blog.Title, 
       Authors = blog.Authors.AsQueryable().ToModel(), // (entities are POCOs) 
       // This does not work, because EF does not understand method ToModel(). 
      }; 
} 

(讓我們假設博客可以有一個以上的作者,它的類型是用戶的)。

我可以以某種方式分開的預測和重用他們另一個者裏面?

+1

請訪問http:// stackoverflow.com/a/11679134/861716。 – 2012-08-15 22:35:26

回答

8

這裏的東西,實際工作(在一個簡單的測試應用程序),只選擇所需的字段:

namespace Entities 
{ 
    public class BlogPost 
    { 
     public virtual int Id { get; set; } 
     public virtual string Title { get; set; } 
     public virtual DateTime Created { get; set; } 
     public virtual ICollection<User> Authors { get; set; } 
    } 

    public class User 
    { 
     public virtual int Id { get; set; } 
     public virtual string Name { get; set; } 
     public virtual string Email { get; set; } 
     public virtual byte[] Password { get; set; } 
     public virtual ICollection<BlogPost> BlogPosts { get; set; } 
    } 
} 

namespace Models 
{ 
    public class BlogPostModel 
    { 
     public string Title { get; set; } 
     public IEnumerable<UserModel> Authors { get; set; } 
    } 

    public class UserModel 
    { 
     public string Name { get; set; } 
     public string Email { get; set; } 
    } 

    public static class BlogPostModelExtensions 
    { 
     public static readonly Expression<Func<BlogPost, BlogPostModel>> ToModelConverterExpression = 
      p => 
      new BlogPostModel 
      { 
       Title = p.Title, 
       Authors = p.Authors.AsQueryable().Select(UserModelExtensions.ToModelConverterExpression), 
      }; 

     public static readonly Func<BlogPost, BlogPostModel> ToModelConverterFunction = ToModelConverterExpression.Compile(); 

     public static IQueryable<BlogPostModel> ToModel(this IQueryable<BlogPost> blogPosts) 
     { 
      return blogPosts.Select(ToModelConverterExpression); 
     } 

     public static IEnumerable<BlogPostModel> ToModel(this IEnumerable<BlogPost> blogPosts) 
     { 
      return blogPosts.Select(ToModelConverterFunction); 
     } 
    } 

    public static class UserModelExtensions 
    { 
     public static readonly Expression<Func<User, UserModel>> ToModelConverterExpression = 
      u => 
      new UserModel 
      { 
       Name = u.Name, 
       Email = u.Email, 
      }; 

     public static readonly Func<User, UserModel> ToModelConverterFunction = ToModelConverterExpression.Compile(); 

     public static IQueryable<UserModel> ToModel(this IQueryable<User> users) 
     { 
      return users.Select(ToModelConverterExpression); 
     } 

     public static IEnumerable<UserModel> ToModel(this IEnumerable<User> users) 
     { 
      return users.Select(ToModelConverterFunction); 
     } 
    } 
} 

爲了測試它,而不實際創建一個數據庫:

var blogPostsQuery = (
    from p in context.BlogPosts 
    where p.Title.StartsWith("a") 
    select p).ToModel(); 
Console.WriteLine(((ObjectQuery)blogPostQuery).ToTraceString()); 
+3

好主意!但我認爲這不是數據庫中發生的「嵌套」投影。它將加載完整的'Author'實體,然後在內存中的setter中投影,即拋出一些或許多加載的列/屬性。 – Slauma 2012-08-15 22:35:56

+0

@Slauma哦,你說的對,我錯過了。我會考慮一下。 – hvd 2012-08-15 22:39:00

+0

這將編譯和運行正常,但@Slauma是正確的。我檢查了探查,並檢索來自DB整個用戶。你認爲什麼,它是可以解決的嗎?謝謝! – jakubka 2012-08-15 22:57:50