无法在实体类型BusinessEntitys.Product上设置字段/属性CartItems

时间:2015-03-24 14:29:22

标签: c# asp.net entity-framework wcf ado.net

我花了很多时间(包括广泛的Google搜索)试图找出问题所在。不幸的是,没有成功。 我得到的错误是:"无法在实体类型BusinessEntitys.Product上设置字段/属性CartItems。有关详细信息,请参阅InnerException。" innerExeption null 。 当我尝试通过WCF调用函数 addCartItem 时,在addToCart()函数中发生错误。当调用到达DAL并尝试在db上下文中保存新对象时,它失败了。

public void AddToCart(int id)
{
    // Retrieve the product from the database.           
    ShoppingCartId = GetCartId();

    CartItem cartItem = new BLFrontend().getAllCartItems().SingleOrDefault(
         c => c.CartItemId == ShoppingCartId
         && c.ProductId == id);
    if (cartItem == null)
    {
        Product temp = new BLFrontend().getAllProducts().SingleOrDefault(
             p => p.ProductId == id);
        // Create a new cart item if no cart item exists.                 
        cartItem = new CartItem
        {
            CartItemId = Guid.NewGuid().ToString(),
            ProductId = id,
            CartId_ = ShoppingCartId,
            Product = temp,
            Quantity = 1,
        };

        new BLFrontend().addCartItem(cartItem);//The problem starts from here
    }
    else
    {
        cartItem.Quantity++;
        //update
    }

我在我的项目中使用EF,这是模型:

namespace BusinessEntitys
{
using System;
using System.Collections.Generic;

public partial class CartItem
{
    public string CartItemId { get; set; }
    public string CartId_ { get; set; }
    public int Quantity { get; set; }
    public int ProductId { get; set; }

    public virtual Product Product { get; set; }
}
}

包含在CratItem中的类产品:

    namespace BusinessEntitys
    {
    using System;
    using System.Collections.Generic;
    using System.Linq; // added this

    public partial class Product
    {
        public Product()
        {
            this.ItemInOrders = new HashSet<ItemInOrder>();
            this.CartItems = new HashSet<CartItem>();
        }

        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public double ProductBasePrice { get; set; }
        public double ProductDiscount { get; set; }
        public string ProductDescription { get; set; }
        public string ProductImageURL { get; set; }
        public string ProductQualityLevel { get; set; }
        public string ProductCategory { get; set; }

        public virtual ICollection<CartItem> CartItems { get; set; }
    }
}

我的BusinessEntitys是:

namespace BusinessEntitys
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;

    public partial class StoreDBEntities : DbContext
    {
        public StoreDBEntities()
            : base("name=StoreDBEntities")
        {
            base.Configuration.ProxyCreationEnabled = false;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<Client> Clients { get; set; }
        public virtual DbSet<ItemInOrder> ItemInOrders { get; set; }
        public virtual DbSet<Order> Orders { get; set; }
        public virtual DbSet<Product> Products { get; set; }
        public virtual DbSet<StockManagment> StockManagments { get; set; }
        public virtual DbSet<CartItem> CartItems { get; set; }
    }
}

尝试执行命令时,在第二行的DAL中执行Execption: 的 context.CartItems.Add(CartItemToAdd)

 public bool addCartItem(CartItem CartItemToAdd)
        {
            try
            {
                var context = new StoreDBEntities();
                context.CartItems.Add(CartItemToAdd);
                return context.SaveChanges() > 0;

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

stackTracer:

  

StackTrace&#34;在DataAccess.Dal.addCartItem(CartItem CartItemToAdd)中   c:\ Users \ User \ Documents \ Visual Studio   2013 \ Projects \ OrGarden \ DataAccess \ Dal.cs:406行\ r \ n at   BusinessLogicBackend.BLBackend.addCartItem(CartItem cartItemToAdd)in   c:\ Users \ User \ Documents \ Visual Studio   2013 \项目\ OrGarden \ BusinessLogicBackend \ BLBackend.cs:行   293 \ r \ n在SyncInvokeaddCartItem(Object,Object [],Object [])\ r \ n   在System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object   实例,对象[]输入,对象[]&amp;输出)\ r \ n at   System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&安培;   RPC)&#34;串

重要更新:当我删除此作业Product = temp,时, addCartItem 调用成功保存没有问题。只有产品字段仍为 null 。 改变后的代码:

Product temp =  business.getAllProducts().SingleOrDefault(
                     p => p.ProductId == id);
                // Create a new cart item if no cart item exists.                 
                cartItem = new CartItem
                {
                    CartItemId = Guid.NewGuid().ToString(),
                    ProductId = id,
                    CartId_ = ShoppingCartId,
                    Product = temp,
                    Quantity = 1,
                };

                 business.addCartItem(cartItem);

当我从上下文中检索CrartItem时,字段产品仍为 null

任何人都可以帮我解决这个不好的问题吗?

非常感谢, 罗恩

1 个答案:

答案 0 :(得分:1)

首先,我强烈建议您查看Unit of Work patternMSDN version,如果您愿意的话)。

问题是,您每次都在创建BLFrontEndStoreDBEntities的新实例。似乎没有理由这样创建实例。

我不确定BLFrontEnd内部究竟发生了什么,但我敢打赌BLFrontEnd上的每个方法都会创建一个新的StoreDBEntities实例。这可能是例外的原因。

您需要管理实例的生命周期。看看这个:

public void AddToCart(int id)
{
    // Begins new life-cycle of BLFrontend
    var frontend = new BLFrontend();
    // or you can wrap it using statement.
    // using(var frontend = new BLFrontend())
    // {
    //    ... code ...
    // }

    // Retrieve the product from the database.           
    ShoppingCartId = GetCartId();

    CartItem cartItem = frontend.getAllCartItems().SingleOrDefault(
         c => c.CartItemId == ShoppingCartId
         && c.ProductId == id);
    if (cartItem == null)
    {
        Product temp = frontend.getAllProducts().SingleOrDefault(
             p => p.ProductId == id);
        // Create a new cart item if no cart item exists.                 
        cartItem = new CartItem
        {
            CartItemId = Guid.NewGuid().ToString(),
            ProductId = id,
            CartId_ = ShoppingCartId,
            Product = temp,
            Quantity = 1,
        };

        frontend.addCartItem(cartItem);//The problem starts from here
    }
    else
    {
        cartItem.Quantity++;
        //update
    }

    // end of life-cycle of the instance.
    frontend.Dispose();
}


public class BLFrontEnd : IDispose
{
    private readonly StoreDBEntities dbContext;
    public BLFrontEnd()
    {
        dbContext = new StoreDBEntities();
    }

    public void Dispose()
    {
        dbContext.Dispose();
    }

    public IQueryable<Cart> getAllCartItems()
    {
       // your logics...
       return dbContext.Carts.AsQueryable();
    }

    public IQueryable<Product> getAllProducts()
    {
       // your logics...
       return dbContext.Products.AsQueryable();
    }

    public bool addCartItem(CartItem CartItemToAdd)
        {
            try
            {
                //var context = new StoreDBEntities();
                dbContext.CartItems.Add(CartItemToAdd);
                return context.SaveChanges() > 0;

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
}

正如您所看到的,“工作”始于AddToCart()方法的开头,并以方法的尾部结束。这就是“一件作品”的生命周期。在生命周期中,每个资源都处于相同的环境中。这意味着生命周期中的每个代码都将使用相同的资源实例。它避免了不必要的新实例创建。

此代码不太好,您需要重构才能满足您的用例和体系结构。但我希望你明白这一点。

<强>被修改

好的,要将实际问题与你的BL分开,你可以试试这个:

public void AddToCart(int id)
{
    // use StoreDBEntities directly, instead of BLFrontend.
    using(var dbContext = new StoreDBEntities())
    {
        // Retrieve the product from the database.           
        ShoppingCartId = 123; // use magic number for this test.

        // and use dbContext directly.
        CartItem cartItem = dbContext.Carts.SingleOrDefault(
             c => c.CartItemId == ShoppingCartId
             && c.ProductId == id);
        if (cartItem == null)
        {
            Product temp = dbContext.Products.SingleOrDefault(
                 p => p.ProductId == id);
            // Create a new cart item if no cart item exists.                 
            cartItem = new CartItem
            {
                CartItemId = Guid.NewGuid().ToString(),
                ProductId = id,
                CartId_ = ShoppingCartId,
                Product = temp,
                Quantity = 1,
            };

            dbContext.Carts.Add(cartItem);
        }
        else
        {
            cartItem.Quantity++;
            //update
        }

        dbContext.SaveChanges();
    }
}