我花了很多时间(包括广泛的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 。
任何人都可以帮我解决这个不好的问题吗?
非常感谢, 罗恩
答案 0 :(得分:1)
首先,我强烈建议您查看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);
}
}
}
正如您所看到的,“工作”始于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();
}
}