如何使用 c# 在数据库优先方法中拥有审计列?
How can I have audit columns in a database-first approach using c#?
我需要为我的 MVC 项目(Web 应用程序)中的所有表添加审计列(创建者、创建者、修改者和修改者)。我想有一个基础 class 这 4 列并继承所有其他 classes。但我使用的是数据库优先方法,因此 EF 生成了所有 classes。我不确定如何添加审计列和基础 class 继承。
我假设无法先通过 EF 数据库执行您想要的操作。但是为了将特定字段添加到数据库的所有表中,您可以对 Sql 服务器中的每个字段使用以下代码,然后更新您的 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
首先是数据库意味着您必须手动将所有字段添加到数据库中,而且 AFAIK 没有继承。您可以编写一个 SQL 脚本来添加这些列。正如马哈尔所说。但是你仍然缺少继承权。
或者你先切换到代码。然后您可以定义一个接口并在代码中处理审计。如图here。
例如,我使用这个接口:
/// <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; }
}
用户提供者接口定义如下:
/// <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();
}
出于测试目的,您现在可以使用 ambient context/service 传送当前用户或您需要测试您的逻辑的任何用户。
我需要为我的 MVC 项目(Web 应用程序)中的所有表添加审计列(创建者、创建者、修改者和修改者)。我想有一个基础 class 这 4 列并继承所有其他 classes。但我使用的是数据库优先方法,因此 EF 生成了所有 classes。我不确定如何添加审计列和基础 class 继承。
我假设无法先通过 EF 数据库执行您想要的操作。但是为了将特定字段添加到数据库的所有表中,您可以对 Sql 服务器中的每个字段使用以下代码,然后更新您的 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
首先是数据库意味着您必须手动将所有字段添加到数据库中,而且 AFAIK 没有继承。您可以编写一个 SQL 脚本来添加这些列。正如马哈尔所说。但是你仍然缺少继承权。
或者你先切换到代码。然后您可以定义一个接口并在代码中处理审计。如图here。 例如,我使用这个接口:
/// <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; }
}
用户提供者接口定义如下:
/// <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();
}
出于测试目的,您现在可以使用 ambient context/service 传送当前用户或您需要测试您的逻辑的任何用户。