首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Entity Framework自动填充错误的实体

Entity Framework自动填充错误的实体
EN

Stack Overflow用户
提问于 2018-06-10 04:12:21
回答 1查看 67关注 0票数 1

我正在开发的音乐商店示例应用程序与ASP.NET的MVC,实体框架和WCF。

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

我已经写了一个种子方法,它工作得很好,但是当我试图向Cart添加一个Album时,另一个重复的Album也被添加到Album表中,同时还添加了重复的Artists。当我在填充Cart对象时添加Album = album语句时,就会发生这种情况。我添加了这条语句,因为当我创建视图时,它会为item.Album.Title条目生成null

这是我的代码:

代码语言:javascript
复制
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,
                        Album = album
                    };

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

模型类:

代码语言:javascript
复制
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.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; }
    }
}

种子方法:

代码语言:javascript
复制
namespace MusicStore.Data
{
    internal class CommonDBInitializer : CreateDatabaseIfNotExists<MusicStoreEntities>
    {
        protected override void Seed(MusicStoreEntities context)
        {
            var genres1 = new List<Genre>
            {
                new Genre
                {
                    Name = "Rock",
                    Description = "Rock",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Jazz",
                    Description = "Jazz",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Metal",
                    Description = "Metal",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Alternative",
                    Description = "Alternative",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Disco",
                    Description = "Disco",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Blues",
                    Description = "Blues",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Latin",
                    Description = "Latin",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Reggae",
                    Description = "Reggae",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Pop",
                    Description = "Pop",
                    Albums = new List<Album>()
                },
                new Genre
                {
                    Name = "Classical",
                    Description = "Classical",
                    Albums = new List<Album>()
                },
            };
            genres1.ForEach(d => context.Genres.Add(d));
            context.SaveChanges();

            var artist1 = new List<Artist>
            {
                new Artist
                {
                    Name = "Aaron Copland & London Symphony Orchestra",

                },
                 new Artist
                {
                    Name = "Barry Wordsworth & BBC Concert Orchestra",

                },

            };

            artist1.ForEach(d => context.Artists.Add(d));
            context.SaveChanges();

            var album1 = new List<Album>
            {
                new Album { Title = "The Best Of Men At Work",  Price = 8.99M,  AlbumArtUrl = "/Content/Images/placeholder.gif",Genre = genres1.FirstOrDefault(d => d.GenreId == 1), Artist  = artist1.FirstOrDefault(d => d.ArtistId == 1) },
               new Album { Title = "A Copland Celebration, Vol. I",  Price = 8.99M, AlbumArtUrl = "/Content/Images/placeholder.gif",Genre = genres1.FirstOrDefault(d => d.GenreId == 2),Artist  = artist1.FirstOrDefault(d => d.ArtistId == 2) },

            };

            album1.ForEach(s => context.Albums.Add(s));

            context.SaveChanges();

        }
    }

控制器:

代码语言:javascript
复制
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");
        }

    }
}

查看:

代码语言:javascript
复制
@model MusicStore.Web.ViewModels.ShoppingCartViewModel
@{
    ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script>

<h3>
    <em>Review</em> your cart:
</h3>
<p class="button">
    @Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<table>
    <tr>
        <th>
            Album Name
        </th>
        <th>
            Price (each)
        </th>
        <th>
            Quantity
        </th>
        <th></th>
    </tr>
    @foreach (var item in Model.CartItems)
    {
        <tr id="row-@item.RecordId">
            <td>
                @Html.ActionLink(item.Album.Title, "Details", "Store", new { id = item.AlbumId }, null)
            </td>
            <td>
                @item.Album.Price
            </td>
            <td id="item-count-@item.RecordId">
                @item.Count
            </td>
            <td>
                <a href="#" class="RemoveLink" data-id="@item.RecordId">Remove from cart</a>
            </td>
        </tr>
    }
    <tr>
        <td>
            Total
        </td>
        <td></td>
        <td></td>
        <td id="cart-total">
            @Model.CartTotal
        </td>
    </tr>
</table>

的问题是:为什么它会以如此不寻常的方式自动填充,以及如何修复它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-10 12:46:29

复制是因为在AddToCart方法中实例化了一个新的上下文MusicStoreEntities。该上下文不知道您通过album参数传递的Album实体的任何信息。

所以当你写这段代码的时候:

代码语言:javascript
复制
cartItem = new Cart
{
    // [...]
    Album = album
};

名为db.Carts.Add(cartItem);cartItem将处于Added状态。EF还将检查cartItem对象图,并发现album未被新上下文跟踪(请记住,此实例来自您的方法的参数),然后默认情况下,它也会将该实体置于Added状态。EF将对album对象图执行相同的操作,您也将在Added状态上获得该专辑的艺术家。当调用db.SaveChanges();时,每个具有Added状态的实体都会被认为是在数据库中生成一个新的插入,所以这就是为什么要进行复制。

要解决这个问题,您可以调用db.Attach(album),让context来处理实体,如下所示:

代码语言:javascript
复制
using (MusicStoreEntities db = new MusicStoreEntities())
{
     db.Albums.Attach(album);

    // [...]
}

或者不使用album实例,您可以只设置外键属性AlbumId,而不使用Album属性赋值。因此,在创建新购物车项目时,您将拥有以下内容:

代码语言:javascript
复制
cartItem = new Cart
{
    AlbumId = album.AlbumId,
    CartId = ShoppingCartID,
    Count = 1,
    DateCreated = DateTime.Now
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50778136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档