【问题标题】:Stored Procedures to insert into History table on Create/Update/Delete?在创建/更新/删除时插入历史表的存储过程?
【发布时间】:2015-03-13 19:07:13
【问题描述】:

我正在开发 MVC5/EF 代码优先应用程序。有谁知道如何实现存储过程,以便每当新记录为inserted 或当前记录updated 时,该记录都会存储在我的INV_AssetsHistory 表中?

我的INV_Assets 表定义为:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using GridMvc.DataAnnotations;
using System.Web.Mvc;
using InventoryTracker.Models;

namespace InventoryTracker.Models
{
    [GridTable(PagingEnabled = true, PageSize = 30)]
    public class INV_Assets 
    {
        // Setting GridColumn Annotations allows you to use AutoGenerateColumns on view to auto create the Grid based on the model.


        public int Id { get; set; }

        public int Model_Id { get; set; }
        [ForeignKey("Model_Id")]
        public virtual INV_Models Model { get; set; }

        [Required]
        public int Manufacturer_Id { get; set; }
        [ForeignKey("Manufacturer_Id")]
        public virtual INV_Manufacturers Manufacturer { get; set; }

        [Required]
        public int Type_Id { get; set; }
        [ForeignKey("Type_Id")]
        public virtual INV_Types Type { get; set; }

        [Required]
        public int Location_Id { get; set; }
        [ForeignKey("Location_Id")]
        public virtual INV_Locations Location { get; set; }

        public int Vendor_Id { get; set; }
        [ForeignKey("Vendor_Id")]
        public virtual INV_Vendors Vendor { get; set; }

        [Required]
        public int Status_Id { get; set; }
        [ForeignKey("Status_Id")]
        public virtual INV_Statuses Status { get; set; }

        public string ip_address { get; set; }

        public string mac_address { get; set; }

        [DataType(DataType.MultilineText)]
        public string note { get; set; }
        public string owner { get; set; }

        //[DataType(DataType.Currency)]
        //[DisplayFormat(DataFormatString="{0:C}", ApplyFormatInEditMode=true)]
        [DisplayFormat(DataFormatString = "{0:#,###0.00}", ApplyFormatInEditMode=true)]
        public decimal cost { get; set; }
        public string po_number { get; set; }

        [DataType(DataType.MultilineText)]
        public string description { get; set; }

        public int invoice_number{ get; set; }

        [Required]
        public string serial_number { get; set; }

        [Required]
        public string asset_tag_number { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? acquired_date { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? disposed_date { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? verified_date { get; set; }

        [Required]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime created_date { get; set; }

        [Required]
        public string created_by { get; set; }

        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
        public DateTime? modified_date { get; set; }

        public string modified_by { get; set; }

        // Flag to specify if item is available? (Not signed out, not auctioned, recycled, etc.)
        //public bool available { get; set; }
    }
}

我的INV_AssetsHistory 表是这样设置的(我认为这是一个独立的表,没有将其链接到其他表的键值;这与INV_Assets 之间的唯一主要区别是Id当前表的字段和用于指定资产的AssetsId):

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using GridMvc.DataAnnotations;
using System.Web.Mvc;
using InventoryTracker.Models;

namespace InventoryTracker.Models
{
    public class INV_AssetsHistory
    {
        public int Id { get; set; }

        [Required]
        public int AssetId { get; set; }

        //public int Model_Id { get; set; }
        //[ForeignKey("Model_Id")]
        public virtual INV_Models Model { get; set; }

        [Required]
        //public int Manufacturer_Id { get; set; }
        //[ForeignKey("Manufacturer_Id")]
        public virtual INV_Manufacturers Manufacturer { get; set; }

        [Required]
        //public int Type_Id { get; set; }
        //[ForeignKey("Type_Id")]
        public virtual INV_Types Type { get; set; }

        [Required]
        //public int Location_Id { get; set; }
        //[ForeignKey("Location_Id")]
        public virtual INV_Locations Location { get; set; }

        //public int Vendor_Id { get; set; }
        //[ForeignKey("Vendor_Id")]
        public virtual INV_Vendors Vendor { get; set; }

        [Required]
        //public int Status_Id { get; set; }
        //[ForeignKey("Status_Id")]
        public virtual INV_Statuses Status { get; set; }

        public string ip_address { get; set; }

        public string mac_address { get; set; }

        [DataType(DataType.MultilineText)]
        public string note { get; set; }
        public string owner { get; set; }

        //[DataType(DataType.Currency)]
        //[DisplayFormat(DataFormatString="{0:C}", ApplyFormatInEditMode=true)]
        [DisplayFormat(DataFormatString = "{0:#,###0.00}", ApplyFormatInEditMode = true)]
        public decimal cost { get; set; }
        public string po_number { get; set; }

        [DataType(DataType.MultilineText)]
        public string description { get; set; }

        public int invoice_number { get; set; }

        [Required]
        public string serial_number { get; set; }

        [Required]
        public string asset_tag_number { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? acquired_date { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? disposed_date { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime? verified_date { get; set; }

        [Required]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime created_date { get; set; }

        [Required]
        public string created_by { get; set; }

        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
        public DateTime? modified_date { get; set; }

        public string modified_by { get; set; }
    }
}

我正在阅读THIS 文章并尝试实现我想要的功能。在我的InventoryTrackerContext.cs 文件中,我有以下内容:

namespace InventoryTracker.DAL
{
    public class InventoryTrackerContext : DbContext
    {
        public InventoryTrackerContext()
            : base("InventoryTrackerContext")
        {

        }

        public DbSet<INV_Assets> INV_Assets { get; set; }
        public DbSet<INV_Models> INV_Models { get;set; }
        public DbSet<INV_Manufacturers> INV_Manufacturers { get;set; }
        public DbSet<INV_Types> INV_Types { get; set; }
        public DbSet<INV_Locations> INV_Locations { get; set; }
        public DbSet<INV_Vendors> INV_Vendors { get; set; }
        public DbSet<INV_Statuses> INV_Statuses { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
             modelBuilder.Entity<INV_Assets>().MapToStoredProcedures();
        }

在阅读这篇文章时,我添加了这个 (modelBuilder.Entity&lt;INV_Assets&gt;().MapToStoredProcedures();) 特定的代码行并更新了我的上下文。现在在我的Server Explorer 连接InventoryTrackerContext 中,我有3 个名为INV_Assets_Delete/Insert/Update 的存储过程。例如Update定义为:

CREATE PROCEDURE [dbo].[INV_Assets_Update]
    @Id [int],
    @Model_Id [int],
    @Manufacturer_Id [int],
    @Type_Id [int],
    @Location_Id [int],
    @Vendor_Id [int],
    @Status_Id [int],
    @ip_address [nvarchar](max),
    @mac_address [nvarchar](max),
    @note [nvarchar](max),
    @owner [nvarchar](max),
    @cost [decimal](18, 2),
    @po_number [nvarchar](max),
    @description [nvarchar](max),
    @invoice_number [int],
    @serial_number [nvarchar](max),
    @asset_tag_number [nvarchar](max),
    @acquired_date [datetime],
    @disposed_date [datetime],
    @verified_date [datetime],
    @created_date [datetime],
    @created_by [nvarchar](max),
    @modified_date [datetime],
    @modified_by [nvarchar](max)
AS
BEGIN
    UPDATE [dbo].[INV_Assets]
    SET [Model_Id] = @Model_Id, [Manufacturer_Id] = @Manufacturer_Id, [Type_Id] = @Type_Id, [Location_Id] = @Location_Id, [Vendor_Id] = @Vendor_Id, [Status_Id] = @Status_Id, [ip_address] = @ip_address, [mac_address] = @mac_address, [note] = @note, [owner] = @owner, [cost] = @cost, [po_number] = @po_number, [description] = @description, [invoice_number] = @invoice_number, [serial_number] = @serial_number, [asset_tag_number] = @asset_tag_number, [acquired_date] = @acquired_date, [disposed_date] = @disposed_date, [verified_date] = @verified_date, [created_date] = @created_date, [created_by] = @created_by, [modified_date] = @modified_date, [modified_by] = @modified_by
    WHERE ([Id] = @Id)
END

根据这篇文章,我假设当我更新我的INV_Asset 记录时,这个过程会自动触发。如果是这样,它并没有像我预期的那样向我的INV_AssetsHistory 表添加记录——查看 SQL 似乎不是所指示的。

我是否需要手动修改 myINV_Assets_Update 存储过程,或者是否有几行我忽略/不知道的简单代码来完成我想要完成的事情?有没有经验更丰富的护理来衡量一下?

我目前正在使用本地 DBContext,但在 PROD 中,表将位于 ORACLE 数据库中。

【问题讨论】:

  • INV_ASSET 上的触发器可以快速简单地完成这项工作。
  • 我不确定 EF 是这里的最佳选择,看起来是数据库触发器的完美场景。
  • 你们能否提供一个示例或链接来说明如何设置?我对 Sequel Server/Management Studio 有点熟悉,但 ORACLE 和 Toad 对我来说是新技术/工具。

标签: c# oracle entity-framework stored-procedures dbcontext


【解决方案1】:

正如其他人已经评论的那样,使用触发器,这里是一个例子:

CREATE TRIGGER INV_ASSET_BRIU ON INV_Asset
BEFORE INSERT OR UPDATE
FOR EACH ROW IS
BEGIN
    INSERT INTO INV_AssetHistory(id, col1, col2, ..., action_timestamp)
    VALUES (:NEW.id, :NEW.col1, :NEW.col2, ..., SYSTIMESTAMP);
END;

使用此触发器,每个版本都将插入到表 INV_AssetHistory

【讨论】:

  • 谢谢。我有点知道如何在实际的数据库中解决这个问题(我的经验是使用 SSMS),但是你知道我如何使用本地 DBContext InventoryTrackerContext 我目前用于我的应用程序来实现/测试这个触发器吗?如果有帮助,我正在使用 VS2013。
  • 我不知道如何使用 SSMS 创建触发器,但肯定有可能在 T-SQL 中创建触发器。
  • 你能详细说明一下吗?我在 Sequel Server Management Studio (SSMS) 中完成了存储过程,但没有对触发器进行太多实验——在 VS2013 中也从未做过。
  • 选择触发动作INSERT和UPDATE;然后写:INSERT INTO INV_AssetHistory SELECT * FROM inserted 作为插入/更新语句(inserted 包含新值作为 Oracle 中的 :NEW
猜你喜欢
  • 2022-07-30
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-19
  • 2013-11-07
  • 2011-03-03
相关资源
最近更新 更多