无法使用映射存储过程插入数据库

时间:2015-10-27 23:43:53

标签: asp.net entity-framework asp.net-mvc-5 entity-framework-6

我正在使用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

2 个答案:

答案 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

这是我所拥有的插入映射的修剪屏幕截图: Column binding for mapped sproc