您好我正在使用SQL Server 2014 我正在使用ef6 和mvc5 每次我尝试保存订单时,整个数据库都会重复,请帮忙 订单控制器如下 我看着jquery.unobtrusive-ajax,我认为它已被使用过了 并且项目中没有返回部分视图
public class OrderController : Controller
{
// GET: Order
[HttpGet]
public ActionResult Index()
{
return View(new Order());
}
[HttpPost]
[ValidateInput(true)]
public ActionResult Index(Order Order)
{
try
{
//OrderValidator validator = new OrderValidator();
var upload = Request.Files["ticketFile"];
if (ModelState.IsValid)//&& validator.Validate(Order).IsValid)
{
using (SaliceContext db = new SaliceContext())
{
//bool isDetached = db.Entry(Order).State == EntityState.Detached;
//if (isDetached)
// db.Orders.Attach(Order);
//db.ProxyCreationEnabled = false;
//db.Entry(Order).State = EntityState.Added;
//db.Entry(Order).State = EntityState.Detached;
Order.OrderNumber = Guid.NewGuid();
db.Orders.Add(Order);
db.SaveChanges();
if (upload != null && upload.ContentLength > 0 && (Path.GetExtension(upload.FileName) == ".pdf" || Path.GetExtension(upload.FileName) == ".docx"))
{
string path = Path.Combine(SaliceConstants.LOI, Order.id.ToString() + Path.GetExtension(upload.FileName));//.Replace("\\", "/");
upload.SaveAs(Server.MapPath(path));
Order.File = path;
db.SaveChanges();
}
db.Dispose();
}
return RedirectToAction("SaleConfirmed", "Order", new { orderNumber = Order.OrderNumber });
//return "Order Saved your comfirmation key: " + Order.OrderNumber;
}
}
catch(Exception ex)
{
ViewBag.Error = "An error happend"; return RedirectToAction("Error","Error");
//return "An error happend";
}
return View(new Order());//"An error happend";
}
public ActionResult SaleConfirmed(Guid orderNumber)
{
try
{
ViewBag.Number = orderNumber;
return View();
}
catch
{
ViewBag.Error = "An error happend"; return RedirectToAction("Error", "Error");
}
return View();
}
}
实体
public class Order
{
public Order()
{
using (SaliceContext db = new SaliceContext())
{
this.Ports = db.Ports.ToList();
this.PaymentTypes = db.PaymentTypes.ToList();
this.Products = db.Products.ToList();
this.Grades = db.Grades.ToList();
this.Packings = db.Packings.ToList();
this.Inspections = db.Inspections.ToList();
this.OrderNumber = new Guid();
db.Dispose();
}
}
[Key]
public int id { get; set; }
public Guid OrderNumber { get; set; }
[LocalDisplayName("Name")]
[Required(ErrorMessage = "*")]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string Name { get; set; }
[LocalDisplayName("LastName")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string LastName { get; set; }
[LocalDisplayName("Compay")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string Company { get; set; }
[LocalDisplayName("Position")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string Position { get; set; }
[LocalDisplayName("Country")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string Country { get; set; }
[LocalDisplayName("City")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string City { get; set; }
[LocalDisplayName("ContactNo")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string ContactNo { get; set; }
[Display(Name = "Email address")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessage = "The email address is required")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
[LocalDisplayName("PortName")]
//[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
//[MaxLength(25, ErrorMessageResourceName = "MaxLength",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public string PortName { get; set; }
[LocalDisplayName("PortValue")]
//[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
//[MaxLength(25, ErrorMessageResourceName = "MaxLength",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public string PortValue { get; set; }
[LocalDisplayName("PortId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int PortId { get; set; }
[LocalDisplayName("PortTypeId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int PortTypeId { get; set; }
public virtual List<Port> Ports { get; set; }
[LocalDisplayName("PaymentTypeId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int PaymentTypeId { get; set; }
public virtual List<PaymentType> PaymentTypes { get; set; }
[LocalDisplayName("Currency")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
[MaxLength(25, ErrorMessageResourceName = "MaxLength",
ErrorMessageResourceType = typeof(ValidationMessages))]
public string Currency { get; set; }
[LocalDisplayName("ProductId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int ProductId { get; set; }
public virtual List<Product> Products { get; set; }
[LocalDisplayName("GradeId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int GradeId { get; set; }
public virtual List<Grade> Grades { get; set;}
[LocalDisplayName("PackingId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int PackingId { get; set; }
public virtual List<Packing> Packings { get; set; }
[LocalDisplayName("Packing")]
//[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
//[MaxLength(25, ErrorMessageResourceName = "MaxLength",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public string Packing { get; set; }
[LocalDisplayName("InspectionId")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public int InspectionId { get; set; }
public virtual List<Inspection> Inspections { get; set; }
[LocalDisplayName("LOI")]
[Required(ErrorMessage = "*")]
//[Required(ErrorMessageResourceName = "Required",
// ErrorMessageResourceType = typeof(ValidationMessages))]
//[MaxLength(25, ErrorMessageResourceName = "MaxLength",
// ErrorMessageResourceType = typeof(ValidationMessages))]
public string LOI { get; set; }
public string File { get; set; }
}
答案 0 :(得分:1)
我认为技术问题是您的代码中的以下几行:
Order.OrderNumber = Guid.NewGuid();
db.Orders.Add(Order);
db.SaveChanges();
让我们快速了解一下控制器内部发生的事情:
我假设您要发布所有模型属性(如果您不这样做,这会在您使EF保持更改后将某些属性设置为其默认值等)。请注意,此时 EF不知道此对象,因为EF不会跟踪其状态。只有在将其添加到DbSet或例如DbSet后才会跟踪它。您从数据库加载它,我们将附加手动加载到 Datacontext 。这是您重新插入数据的主要原因 - EF不知道对象,因此不知道它需要更新。
您正在修改相同订单的OrderNumber,这似乎不正确(您将在保存后更新它正常工作)。我不知道这是否是主键 - 如果这是他们的情况,我假设你只做了这个,因为你在调用Savechanges(主键通道)时遇到了SqlException
您可以采取哪些措施来解决技术问题:
正如您的代码示例所示,您已经与对象 EntityState 进行了搏斗。 正如我上面所写,EF不会跟踪提交的订单。您可以添加以下内容(因为您似乎已经尝试过):
db.Orders.Attach(Order);
这将&#34;重新添加&#34; EF的对象。我们在这里做的是手动告诉EF这个对象(带有它的ID)是从数据库加载的,而是从不同的DbContext(在显示表单/数据的请求中)加载的。 EF DbContext根本无法记住&#34;跨多个WebRequests的对象(因为DbContext在请求之间处理)。 但问题是,EF对象的状态做了什么。在附加对象时,EF将其状态设置为未更改,因为它不知道自加载以来哪些属性发生了更改。 您可以将实体的状态更改为之后修改(因此告知EF&#34;它已更改,在调用SaveChanges时更新所有属性()&#34;):
context.Entry(Order).State = EntityState.Modified;
这会将所有属性标记为已更改(没有Navigationproperties)。
从技术上讲,这应该可以解决您的问题 - 您可以阅读更多相关内容here,但我想提一下其他内容:
通常(至少在我看来)发布完整的模型模型不是一个好主意。问题是为什么?
您对我的包含外键属性进行建模,该外键属性可能已被修改但不应被修改(假设用户选择了他不应该选择的内容)。这可以通过使用允许您包含/排除属性的BindAttribute来改进。 See msdn on BindAttribute
您的模型上有很多属性,这可能只是UI问题所必需的。由于您只有1个模型,因此您无法以不同的形式(例如验证属性等)以不同方式显示相同的数据。例如,在Create usecase中,添加信息消息可能是可选的,但在更新时可能需要它。
最好开始创建一个单独的 Viewmodel ,它只保存页面所需的数据(从而使得例如BindAttribute的使用过时)。