无法在实体类型 BusinessEntitys.Product 上设置 field/property CartItems
Unable to set field/property CartItems on entity type BusinessEntitys.Product
我花了很多时间(包括广泛的 Google 搜索)试图找出问题所在。不幸的是,没有成功。
我得到的错误是:"Unable to set field/property CartItems on entity type BusinessEntitys.Product. See InnerException for details."
innerExeption 是 null。
当我尝试通过 WCF 调用函数 addCartItem 时,addToCart() 函数出现错误。当调用到达 DAL 并尝试将新对象保存在数据库上下文中时,它失败了。
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; }
}
}
class 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; }
}
}
我的 BusinessEntity 是:
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 中的第二行出现异常:
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 "at DataAccess.Dal.addCartItem(CartItem CartItemToAdd) in
c:\Users\User\Documents\Visual Studio
2013\Projects\OrGarden\DataAccess\Dal.cs:line 406\r\n at
BusinessLogicBackend.BLBackend.addCartItem(CartItem cartItemToAdd) in
c:\Users\User\Documents\Visual Studio
2013\Projects\OrGarden\BusinessLogicBackend\BLBackend.cs:line
293\r\n at SyncInvokeaddCartItem(Object , Object[] , Object[] )\r\n
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object
instance, Object[] inputs, Object[]& outputs)\r\n at
System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&
rpc)" string
重要更新:当我删除此作业时 Product = temp,
addCartItem 调用成功保存,没有问题。只有字段 Product 保持 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 时,字段 Product 仍然是 null。
谁能帮我解决那个坏问题?
非常感谢,
罗恩
首先,如果你愿意,我强烈建议你看看Unit of Work pattern (MSDN version。
问题是,您每次都在创建 BLFrontEnd
和 StoreDBEntities
的新实例。似乎没有理由这样创建实例。
我不确定 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);
}
}
}
如您所见,'A work' 开始于 AddToCart()
方法的头部,结束于方法的尾部。那就是 'A work' 的生命周期。在生命周期中,每个资源都处于相同的上下文中。这意味着生命周期中的每个代码都将使用相同的资源实例。它避免了不必要的新实例创建。
这段代码不是很好,您需要重构以满足您的用例和架构。但我希望你明白了。
已编辑
好的,为了将实际问题与您的 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();
}
}
我花了很多时间(包括广泛的 Google 搜索)试图找出问题所在。不幸的是,没有成功。 我得到的错误是:"Unable to set field/property CartItems on entity type BusinessEntitys.Product. See InnerException for details." innerExeption 是 null。 当我尝试通过 WCF 调用函数 addCartItem 时,addToCart() 函数出现错误。当调用到达 DAL 并尝试将新对象保存在数据库上下文中时,它失败了。
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; }
}
}
class 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; }
}
}
我的 BusinessEntity 是:
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 中的第二行出现异常: 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 "at DataAccess.Dal.addCartItem(CartItem CartItemToAdd) in c:\Users\User\Documents\Visual Studio 2013\Projects\OrGarden\DataAccess\Dal.cs:line 406\r\n at BusinessLogicBackend.BLBackend.addCartItem(CartItem cartItemToAdd) in c:\Users\User\Documents\Visual Studio 2013\Projects\OrGarden\BusinessLogicBackend\BLBackend.cs:line 293\r\n at SyncInvokeaddCartItem(Object , Object[] , Object[] )\r\n at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)\r\n at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)" string
重要更新:当我删除此作业时 Product = temp,
addCartItem 调用成功保存,没有问题。只有字段 Product 保持 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 时,字段 Product 仍然是 null。
谁能帮我解决那个坏问题?
非常感谢, 罗恩
首先,如果你愿意,我强烈建议你看看Unit of Work pattern (MSDN version。
问题是,您每次都在创建 BLFrontEnd
和 StoreDBEntities
的新实例。似乎没有理由这样创建实例。
我不确定 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);
}
}
}
如您所见,'A work' 开始于 AddToCart()
方法的头部,结束于方法的尾部。那就是 'A work' 的生命周期。在生命周期中,每个资源都处于相同的上下文中。这意味着生命周期中的每个代码都将使用相同的资源实例。它避免了不必要的新实例创建。
这段代码不是很好,您需要重构以满足您的用例和架构。但我希望你明白了。
已编辑
好的,为了将实际问题与您的 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();
}
}