实体框架不加载相关对象

Posted

技术标签:

【中文标题】实体框架不加载相关对象【英文标题】:Entity Framework do not load related objects 【发布时间】:2018-11-20 03:24:39 【问题描述】:

我正在使用 ASP.NET MVC、Entity Framework 和 WCF 开发音乐商店示例应用。

这是一个分层的应用程序,它有一个实体的公共层。

AddToCart Action 方法中,Album 对象填充得很好,但是当 wcf 加载购物车对象时,在购物车保存后,关联的 Album 对象为 Null,可能是一些序列化问题(我不知道) ,在视图@foreach (var item in Model.CartItems)item.Album.Title 变为空

这是我的代码:

public static void AddToCart(Album album, string ShoppingCartID)

            using (MusicStoreEntities db = new MusicStoreEntities())
            
                // Get the matching cart and album instances
                var cartItem = db.Carts.SingleOrDefault(
                    c => c.CartId == ShoppingCartID
                         && c.AlbumId == album.AlbumId);

                if (cartItem == null)
                
                    // Create a new cart item if no cart item exists
                    cartItem = new Cart
                    
                        AlbumId = album.AlbumId,
                        CartId = ShoppingCartID,
                        Count = 1,
                        DateCreated = DateTime.Now                           
                    ;

                    db.Carts.Add(cartItem);
                
                else
                
                    // If the item does exist in the cart, then add one to the quantity
                    cartItem.Count++;
                

                // Save changes
                db.SaveChanges();
            


public static List<Cart> GetCartItems(string ShoppingCartID)
        
            using (MusicStoreEntities db = new MusicStoreEntities())
            
               return db.Carts.Where(cart => cart.CartId == ShoppingCartID).ToList();

            
        

控制器

namespace MusicStore.Web.Controllers

    public class ShoppingCartController : Controller
    
        MusicShoppingCartMgr.Cart serviceref1 = new MusicShoppingCartMgr.Cart();
        MusicShoppingCartMgr.iShoppingCart servicemethodref1 = new iShoppingCartClient();
        //
        // GET: /ShoppingCart/
        public ActionResult Index()
        
            var cart = ShoppingCart.GetCart(this.HttpContext);

            // Set up our ViewModel
            var viewModel = new ShoppingCartViewModel
            
                CartItems = cart.GetCartItems(cart.ShoppingCartId),
                CartTotal = cart.GetTotal(cart.ShoppingCartId)
            ;

            // Return the view
            return View(viewModel);
        
        //
        // GET: /Store/AddToCart/5

        public ActionResult AddToCart(int id)
        
            var addedAlbum = servicemethodref1.GetAlbum(id);

            // Add it to the shopping cart
            var cart = ShoppingCart.GetCart(this.HttpContext);

            cart.AddToCart(addedAlbum, cart.ShoppingCartId);

            // Go back to the main store page for more shopping
            return RedirectToAction("Index");
        


    

模型类

namespace MusicStore.Core

    [Serializable]
    [DataContract]
    public class Cart
    
        [Key]
        [DataMember]
        public int RecordId  get; set; 
        [DataMember]
        public string CartId  get; set; 
        [DataMember]
        public int AlbumId  get; set; 
        [DataMember]
        public int Count  get; set; 
        [DataMember]
        public System.DateTime DateCreated  get; set; 
        [DataMember]
        public virtual Album Album  get; set; 
    


namespace MusicStore.Core

    [Serializable]
    [DataContract]
    //[Bind(Exclude = "AlbumId")]
    public class Album
    
        [DataMember]
        [ScaffoldColumn(false)]
        public int AlbumId  get; set; 

        [DataMember]
        [DisplayName("Genre")]
        public int GenreId  get; set; 

        [DataMember]
        [DisplayName("Artist")]
        public int ArtistId  get; set; 

         [DataMember]
        [Required(ErrorMessage = "An Album Title is required")]
        [StringLength(160)]
        public string Title  get; set; 

         [DataMember]
        [Required(ErrorMessage = "Price is required")]
        [Range(0.01, 100.00,
            ErrorMessage = "Price must be between 0.01 and 100.00")]
        public decimal Price  get; set; 

         [DataMember]
        [DisplayName("Album Art URL")]
        [StringLength(1024)]
        public string AlbumArtUrl  get; set; 

           [DataMember]
         public virtual Genre Genre  get; set; 
           [DataMember]
        public virtual Artist Artist  get; set; 
         public virtual List<OrderDetail> OrderDetails  get; set; 
    

数据库上下文

namespace MusicStore.Data

    public class MusicStoreEntities : DbContext
    
        public MusicStoreEntities()
            : base("MusicStoreEntities")
        
            var ensureDLLIsCopied = System.Data.Entity.SqlServer.SqlProviderServices.Instance;

            this.Configuration.ProxyCreationEnabled = false;

            Database.SetInitializer<MusicStoreEntities>(new CreateDatabaseIfNotExists<MusicStoreEntities>());
            Database.SetInitializer(new CommonDBInitializer());
        

        public DbSet<Album> Albums  get; set; 
        public DbSet<Genre> Genres  get; set; 
        public DbSet<Artist> Artists  get; set; 
        public DbSet<Cart> Carts  get; set; 
        public DbSet<Order> Orders  get; set; 
        public DbSet<OrderDetail> OrderDetails  get; set; 
    

问题是:为什么Album对象没有加载到Cart对象内部,如何解决?

【问题讨论】:

【参考方案1】:

默认情况下,Entity Framework 不加载相关对象,以帮助防止在将一对多或多对多关系加载到内存时出现潜在的性能问题。

查看您发布的代码,您可以在从GetCartItems 中取出购物车物品时添加.Include("Album")。然后就变成了

public static List<Cart> GetCartItems(string ShoppingCartID)

    using (MusicStoreEntities db = new MusicStoreEntities())
    
        return db.Carts.Include("Album").Where(cart => cart.CartId == ShoppingCartID).ToList();
    

有关加载相关实体的其他一些选项,请参阅 the Entity Framework docs

【讨论】:

您向我展示了一个有效点,但它应该应用于 GetCartItems 方法,我没有发布,所以我将更详细地编辑我的原始问题代码

以上是关于实体框架不加载相关对象的主要内容,如果未能解决你的问题,请参考以下文章

从实体框架中的集合加载相关实体

使用急切加载时,实体框架是不是将所有相关实体加载到无限深度

实体框架 - 停止按需延迟加载相关实体?

实体框架 CTP5 重新加载相关实体

实体框架 - 相关实体性能

使用实体框架6插入已断开的相关实体