我正在使用Entity Framework 6代码优先方法,并且我有以下操作控制器方法来插入master-detail条目:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( Facturas_prueba facturas_prueba, List<FacturasDetalle_prueba> detalle)
{
if (detalle != null && detalle.Count > 0 ) {
for (int i = 0; i <= detalle.Count-1; i++) {
detalle[i].folio = facturas_prueba.folio;
ModelState["detalle[" + i + "].folio"].Errors.Clear(); //Elimina los errores de validaciones del modelo porque ya asignamos manualmente el folio
}
}
else
{
ModelState.AddModelError("folio", "No asignó ningun detalle para el folio"); //Agrega un error de modelo al diccionario de ModelState
}
if (ModelState.IsValid) //Si el estado del model es valido (Todas las validaciones correctas)
{
db.Database.Log = Logger;
db.Facturas_prueba.Add(facturas_prueba);
db.FacturasDetalle_prueba.AddRange(detalle); //AddRange sirve para agregar collecciones
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.almacen = new SelectList(db.CATALMA, "COD_ALM", "NOM_ALM", facturas_prueba.almacen);
ViewBag.cliente = new SelectList(db.CATCTES, "COD_CTE", "NOM_CTE", facturas_prueba.cliente);
ViewBag.usuario = new SelectList(db.FACPARU, "cod_usu", "cod_Alm", facturas_prueba.usuario);
ViewBag.plaza = new SelectList(db.PLAZAS, "PLAZA", "LAST_COD_CTE", facturas_prueba.plaza);
return View(facturas_prueba);
这通常在使用EF的默认方式时有效,但是,现在我正在尝试使用存储过程在每个表中插入(目前只有那个),我在db.SaveChanges()
得到一个例外:< / p>
用户代码未处理System.Data.Entity.Infrastructure.DbUpdateConcurrencyException
存储更新,插入或删除语句会影响意外的行数(0)。自实体加载后,实体可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=472540。
我像这样映射了存储过程,不知道我是否遗漏了什么。字段和参数上的名称相同:
...
modelBuilder.Entity<Facturas_prueba>()
.MapToStoredProcedures(s =>
s.Insert(i => i.HasName("nueva_factura") ));
...
modelBuilder.Entity<FacturasDetalle_prueba>()
.MapToStoredProcedures(s =>
s.Insert(i => i.HasName("nuevo_factura_detalle")));
这让我发疯,数据库优先方法比这更容易。 有什么建议吗?
更新:我在答案之前添加了一个商店程序:
CREATE PROCEDURE nueva_factura(
@folio varchar(10),
@fecha datetime,
@almacen varchar(10),
@cliente varchar(10),
@plaza varchar(10),
@usuario varchar(10),
@id_factura int = 0 OUTPUT
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
--SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO Facturas_prueba
VALUES(@folio, @fecha, @almacen, @cliente, @plaza, @usuario)
SET @id_factura = SCOPE_IDENTITY()
END
GO
答案 0 :(得分:1)
我刚刚发现在存储过程中的标识列中添加 SELECT SCOPE_IDENTITY()语句修复了问题:
ALTER PROCEDURE nueva_factura(
-- Add the parameters for the stored procedure here
@folio varchar(10),
@fecha datetime,
@almacen varchar(10),
@cliente varchar(10),
@plaza varchar(10),
@usuario varchar(10),
@id_factura int = 0 --OUTPUT
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
--SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO Facturas_prueba VALUES(
@folio,@fecha,@almacen,@cliente,@plaza,@usuario
)
SELECT SCOPE_IDENTITY() AS id_factura
END
GO
对于为什么插件需要这样做的评论中的任何说明都将不胜感激。
答案 1 :(得分:0)
谢谢。添加SELECT SCOPE_IDENTITY() AS MyId
为我做了。
这是必要的,至少对我来说,是当实体框架导入存储过程时,它期望MyId的结果......
我最初有return SCOPE_IDENTITY()
,结果为DbUpdateConcurrencyException
,错误为Store update, insert, or delete statement affected an unexpected number of rows (0).
当我将存储过程中的返回值更改为SELECT SCOPE_IDENTITY()
时,我收到错误消息,指出列未正确映射。
使用完整的SELECT ... AS MyId
。