如何使用c#在数据库优先方法中拥有审计列?

如何使用c#在数据库优先方法中拥有审计列?,c#,entity-framework,model-view-controller,audit,ef-database-first,C#,Entity Framework,Model View Controller,Audit,Ef Database First,我需要为MVC项目(web应用程序)中的所有表添加审核列(创建人、创建人、修改人和修改人)。我想用这4列创建一个基类,并继承所有其他类。但我使用的是数据库优先的方法,因此EF已经生成了所有的类。我不确定如何添加审核列和基类继承。我假设不可能首先通过EF数据库执行所需的操作。但是,为了向数据库的所有表中添加特定字段,可以对Sql Server中的每个字段使用以下代码,然后更新EF模型 DECLARE @TableName VARCHAR(100) DECLARE @TableSchema VARC

我需要为MVC项目(web应用程序)中的所有表添加审核列(创建人、创建人、修改人和修改人)。我想用这4列创建一个基类,并继承所有其他类。但我使用的是数据库优先的方法,因此EF已经生成了所有的类。我不确定如何添加审核列和基类继承。

我假设不可能首先通过EF数据库执行所需的操作。但是,为了向数据库的所有表中添加特定字段,可以对Sql Server中的每个字段使用以下代码,然后更新EF模型

DECLARE @TableName VARCHAR(100)
DECLARE @TableSchema VARCHAR(100)
DECLARE @COLUMN_NAME VARCHAR(50)
SET @COLUMN_NAME='CreatedOn' 
DECLARE @COLUMN_DATATYPE VARCHAR(50)
SET @COLUMN_DATATYPE='DateTime'

DECLARE CUR CURSOR FOR
  SELECT TABLE_SCHEMA,
         TABLE_NAME
  FROM   INFORMATION_SCHEMA.TABLES
  WHERE  TABLE_TYPE = 'BASE TABLE'
OPEN CUR
FETCH NEXT FROM CUR INTO @TableSchema,@TableName
WHILE @@FETCH_STATUS = 0
  BEGIN

  DECLARE @SQL NVARCHAR(MAX)
  SET @SQL=NULL
  IF NOT EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS 
       WHERE TABLE_NAME=@TableName AND COLUMN_NAME = @COLUMN_NAME  and Table_Schema=@TableSchema)
  BEGIN
  SET @SQL='ALTER TABLE '+ @TableSchema+'.'+ @TableName +' ADD '+ @COLUMN_NAME + ' '+ @COLUMN_DATATYPE
    PRINT @SQL
    EXEC(@SQL)
  END

  IF EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS 
              WHERE TABLE_NAME=@TableName AND COLUMN_NAME=@COLUMN_NAME and Table_Schema=@TableSchema)
  BEGIN
    PRINT 'Column Already exists in Table'
  END
      FETCH NEXT FROM CUR INTO @TableSchema,@TableName
  END
CLOSE CUR
DEALLOCATE CUR

我假设不可能首先通过EF数据库执行所需的操作。但是,为了向数据库的所有表中添加特定字段,可以对Sql Server中的每个字段使用以下代码,然后更新EF模型

DECLARE @TableName VARCHAR(100)
DECLARE @TableSchema VARCHAR(100)
DECLARE @COLUMN_NAME VARCHAR(50)
SET @COLUMN_NAME='CreatedOn' 
DECLARE @COLUMN_DATATYPE VARCHAR(50)
SET @COLUMN_DATATYPE='DateTime'

DECLARE CUR CURSOR FOR
  SELECT TABLE_SCHEMA,
         TABLE_NAME
  FROM   INFORMATION_SCHEMA.TABLES
  WHERE  TABLE_TYPE = 'BASE TABLE'
OPEN CUR
FETCH NEXT FROM CUR INTO @TableSchema,@TableName
WHILE @@FETCH_STATUS = 0
  BEGIN

  DECLARE @SQL NVARCHAR(MAX)
  SET @SQL=NULL
  IF NOT EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS 
       WHERE TABLE_NAME=@TableName AND COLUMN_NAME = @COLUMN_NAME  and Table_Schema=@TableSchema)
  BEGIN
  SET @SQL='ALTER TABLE '+ @TableSchema+'.'+ @TableName +' ADD '+ @COLUMN_NAME + ' '+ @COLUMN_DATATYPE
    PRINT @SQL
    EXEC(@SQL)
  END

  IF EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS 
              WHERE TABLE_NAME=@TableName AND COLUMN_NAME=@COLUMN_NAME and Table_Schema=@TableSchema)
  BEGIN
    PRINT 'Column Already exists in Table'
  END
      FETCH NEXT FROM CUR INTO @TableSchema,@TableName
  END
CLOSE CUR
DEALLOCATE CUR

Database first意味着您必须手动将所有字段添加到数据库中,如果没有继承的话。您可以编写添加这些列的SQL脚本。正如马亚尔所说。但你仍然缺乏继承权

或者先切换到代码。然后您可以定义一个接口并在代码中处理审计。如图所示。 一、 例如,使用此接口:

    /// <summary>
    /// Adds auditing properties to an entity.
    /// </summary>
    public interface IAuditedEntity
    {
        /// <summary>
        /// Date and time of the entity's creation. Usually in UTC.
        /// </summary>
        /// <remarks>Best set via a <see cref="ITimeProvider"/>.</remarks>
        DateTime DateCreated { get; set; }

        /// <summary>
        /// Identification who created this instance.
        /// </summary>
        /// <remarks>Best set via a <see cref="ICurrentUserIdProvider"/>.</remarks>
        string CreatedBy { get; set; }

        /// <summary>
        /// Date and time of last modification. Usually in UTC.
        /// </summary>
        /// <remarks>Best set via a <see cref="ITimeProvider"/>.</remarks>
        DateTime? DateModified { get; set; }

        /// <summary>
        /// Last one modifiying this instance.
        /// </summary>
        /// <remarks>Best set via a <see cref="ICurrentUserIdProvider"/>.</remarks>
       string ModifiedBy { get; set; }
}
//
///将审核属性添加到实体。
/// 
公共接口IAuditedEntity
{
/// 
///实体创建的日期和时间。通常以UTC为单位。
/// 
///最佳设置通过一个。
DateTime DateCreated{get;set;}
/// 
///创建此实例的标识。
/// 
///最佳设置通过一个。
字符串CreatedBy{get;set;}
/// 
///上次修改的日期和时间。通常以UTC为单位。
/// 
///最佳设置通过一个。
DateTime?DateModified{get;set;}
/// 
///最后一个正在修改此实例。
/// 
///最佳设置通过一个。
字符串由{get;set;}修改
}
用户提供程序界面的定义如下:

    /// <summary>
    /// Interface for providing the current user's id.
    /// </summary>
    public interface ICurrentUserIdProvider
    {
        /// <summary>
        /// Get the id of the curent user.
        /// </summary>
        /// <returns></returns>
        string GetCurrentUserId();
    }
//
///用于提供当前用户id的接口。
/// 
公共接口ICurrentUserIdProvider
{
/// 
///获取当前用户的id。
/// 
/// 
字符串GetCurrentUserId();
}

出于测试目的,您现在可以使用一个数据库来测试当前用户或您需要的任何用户的逻辑。

数据库首先意味着您必须手动将所有字段添加到数据库中,并且确认没有继承。您可以编写添加这些列的SQL脚本。正如马亚尔所说。但你仍然缺乏继承权

或者先切换到代码。然后您可以定义一个接口并在代码中处理审计。如图所示。 一、 例如,使用此接口:

    /// <summary>
    /// Adds auditing properties to an entity.
    /// </summary>
    public interface IAuditedEntity
    {
        /// <summary>
        /// Date and time of the entity's creation. Usually in UTC.
        /// </summary>
        /// <remarks>Best set via a <see cref="ITimeProvider"/>.</remarks>
        DateTime DateCreated { get; set; }

        /// <summary>
        /// Identification who created this instance.
        /// </summary>
        /// <remarks>Best set via a <see cref="ICurrentUserIdProvider"/>.</remarks>
        string CreatedBy { get; set; }

        /// <summary>
        /// Date and time of last modification. Usually in UTC.
        /// </summary>
        /// <remarks>Best set via a <see cref="ITimeProvider"/>.</remarks>
        DateTime? DateModified { get; set; }

        /// <summary>
        /// Last one modifiying this instance.
        /// </summary>
        /// <remarks>Best set via a <see cref="ICurrentUserIdProvider"/>.</remarks>
       string ModifiedBy { get; set; }
}
//
///将审核属性添加到实体。
/// 
公共接口IAuditedEntity
{
/// 
///实体创建的日期和时间。通常以UTC为单位。
/// 
///最佳设置通过一个。
DateTime DateCreated{get;set;}
/// 
///创建此实例的标识。
/// 
///最佳设置通过一个。
字符串CreatedBy{get;set;}
/// 
///上次修改的日期和时间。通常以UTC为单位。
/// 
///最佳设置通过一个。
DateTime?DateModified{get;set;}
/// 
///最后一个正在修改此实例。
/// 
///最佳设置通过一个。
字符串由{get;set;}修改
}
用户提供程序界面的定义如下:

    /// <summary>
    /// Interface for providing the current user's id.
    /// </summary>
    public interface ICurrentUserIdProvider
    {
        /// <summary>
        /// Get the id of the curent user.
        /// </summary>
        /// <returns></returns>
        string GetCurrentUserId();
    }
//
///用于提供当前用户id的接口。
/// 
公共接口ICurrentUserIdProvider
{
/// 
///获取当前用户的id。
/// 
/// 
字符串GetCurrentUserId();
}

出于测试目的,您现在可以使用一个用于测试当前用户或需要测试逻辑的任何用户。

这是一个很好的机会,可以先切换到代码(无论是否迁移)。在代码优先中,这要容易得多。使用database first,您将不得不使用EF6.2,并且很可能有一天Visual Studio将停止支持EDMX设计。这是一个很好的机会,可以先切换到代码(无论是否迁移)。在代码优先中,这要容易得多。首先使用数据库,您将被EF6.2所困扰,并且很可能有一天VisualStudio将停止支持EDMX设计。