5

Verileri almak için Entity Framework kullanan bir ASP.NET MVC uygulamasına sahibim.Entity Framework'deki projeksiyonlar nasıl yeniden kullanılır?

Girişleri Görünüm'e geçirmeden önce Modellere dönüştürmem gerekiyor. Projeksiyonlar çok karmaşık olabilir, ancak basit tutmak:

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

Bu

böyle bir denetleyici olarak kullanılabilir:

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

Çok iyi. Ama eğer bu projeksiyonu başka bir tane içinde kullanmak istersem? Örnek:

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(). 
      }; 
} 

(Blogun birden fazla yazara sahip olabileceğini varsayalım ve bu kullanıcı türündedir).

Çıkıntıları bir şekilde ayırabilir ve başka bir tanesinin içinde yeniden kullanabilir miyim?

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); 
     } 
    } 
} 

aslında bir veritabanı oluşturmadan bunu test etmek için:: İşte

+1

bakınız http: // stackoverflow.com/a/11679134/861716. –

cevap

8

sadece seçmek istenen alanlara (basit bir test uygulamasında) gerçekten çalışıyor şey

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

İyi fikir! Ama bence veritabanında gerçekleşen "iç içe" bir projeksiyon değil. Tam 'Author' varlıklarını yükler ve sonra setterde bellekte projeksiyon yapar, yani yüklenen sütun/özelliklerin bir kısmını veya bir kısmını atlar. – Slauma

+0

@Slauma Oh, haklısın, bunu özledim. Biraz düşüneceğim. – hvd

+0

Bu derleme ve düzgün çalışır, ancak @Slauma haklıdır .. Profiler'i kontrol ettim ve tüm Kullanıcıyı DB'den aldım. Ne düşünüyorsun, çözülebilir mi? Teşekkürler! – jakubka