C# 在EF中动态设置表名
我看到了: 但是,在我的情况下,我不能使用基类。我希望创建一个用户组和周敏感表进行审核,所以在运行时创建它们之前,我不知道将调用什么 因此,如果我在一年的第一周登录,它将是:C# 在EF中动态设置表名,c#,entity-framework,C#,Entity Framework,我看到了: 但是,在我的情况下,我不能使用基类。我希望创建一个用户组和周敏感表进行审核,所以在运行时创建它们之前,我不知道将调用什么 因此,如果我在一年的第一周登录,它将是: Group1\u 01\u 2014 这可能吗?我试图在创建时简单地更改数据库名称,但我得到了关于数据库迁移的标准异常 谢谢 编辑:在有人说分割数据库是愚蠢的之前,要知道我在审计很多。其思想是能够审计大多数事务,根据需要存储它们,而不会严重影响性能 Edit2:也就是说,如果有人有更好的解决方案,我洗耳恭听 解决方案 最
Group1\u 01\u 2014
这可能吗?我试图在创建时简单地更改数据库名称,但我得到了关于数据库迁移的标准异常
谢谢
编辑:在有人说分割数据库是愚蠢的之前,要知道我在审计很多。其思想是能够审计大多数事务,根据需要存储它们,而不会严重影响性能
Edit2:也就是说,如果有人有更好的解决方案,我洗耳恭听
解决方案
最终使用了存储过程:
CREATE FUNCTION GetAuditTableName
(
@db_code CHAR (4)
)
RETURNS CHAR (12)
BEGIN
DECLARE @wkNo CHAR (2)
DECLARE @year CHAR (4)
SELECT @wkNo = REPLACE(STR(DATEPART(WEEK, GETDATE()), 2), SPACE(1), '0')
SELECT @year = STR(DATEPART(YEAR, GETDATE()), 4)
RETURN @db_code + '_' + @year + '_' + @wkNo
END
GO
CREATE PROCEDURE [dbo].[Audit_Insert]
@audi_id_first NVARCHAR (20),
@audi_id_second NVARCHAR (20),
@audi_by NVARCHAR (100),
@audi_on DATETIME,
@audi_details XML,
@tabn_code CHAR (4),
@audt_id INT,
@audi_db_code CHAR (4)
AS
BEGIN
DECLARE @tableName CHAR (12)
SET @tableName = [dbo].GetAuditTableName(@audi_db_code)
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=@tableName and xtype='U')
BEGIN
DECLARE @createSql NVARCHAR(MAX);
SELECT @createSql = 'CREATE TABLE [dbo].' + QUOTENAME(@tableName) + ' (
[audi_id] INT IDENTITY (1, 1) NOT NULL,
[audi_id_first] NVARCHAR (20) NULL,
[audi_id_second] NVARCHAR (20) NULL,
[audi_by] NVARCHAR (100) NOT NULL,
[audi_on] DATETIME NOT NULL,
[audi_details] XML NULL,
[tabn_code] CHAR (4) NULL,
[audt_id] INT NOT NULL,
CONSTRAINT [PK_dbo.' + @tableName + '] PRIMARY KEY CLUSTERED ([audi_id] ASC),
CONSTRAINT [FK_dbo.' + @tableName + '_dbo.tabn_table_name_tabn_code] FOREIGN KEY ([tabn_code]) REFERENCES [dbo].[tabn_table_name] ([tabn_code]),
CONSTRAINT [FK_dbo.' + @tableName + '_dbo.audt_audit_type_audt_id] FOREIGN KEY ([audt_id]) REFERENCES [dbo].[audt_audit_type] ([audt_id])
)'
EXEC sp_executesql @createSql
END
DECLARE @insertSql NVARCHAR(MAX);
SELECT @insertSql = N'INSERT [dbo].' + QUOTENAME(@tableName) + ' ([audi_id_first], [audi_id_second], [audi_by], [audi_on], [audi_details], [tabn_code], [audt_id])
VALUES (@audi_id_first, @audi_id_second, @audi_by, @audi_on, @audi_details, @tabn_code, @audt_id)'
EXEC sp_executesql @insertSql, N'@audi_id_first NVARCHAR (20), @audi_id_second NVARCHAR (20), @audi_by NVARCHAR (100), @audi_on DATETIME, @audi_details XML, @tabn_code CHAR (4), @audt_id INT', @audi_id_first, @audi_id_second, @audi_by, @audi_on, @audi_details, @tabn_code, @audt_id
DECLARE @idSql NVARCHAR(MAX);
SELECT @idSql = 'DECLARE @audi_id INT
SELECT @audi_id = [audi_id]
FROM [dbo].' + QUOTENAME(@tableName) + '
WHERE @@ROWCOUNT > 0 AND [audi_id] = scope_identity()
SELECT t0.[audi_id]
FROM [dbo].' + QUOTENAME(@tableName) + ' AS t0
WHERE @@ROWCOUNT > 0 AND t0.[audi_id] = @audi_id'
EXEC sp_executesql @idSql
END
GO
然后从C#调用这个:
我的下一个任务是让它与IQueryable-OData请求一起工作
解决方案2
CREATE PROCEDURE [dbo].[CreateAuditTableIfNoneExists]
@tableName CHAR (12)
AS
BEGIN
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=@tableName and xtype='U')
BEGIN
DECLARE @createSql NVARCHAR(MAX);
SELECT @createSql = 'CREATE TABLE [dbo].' + QUOTENAME(@tableName) + ' (
[audi_id] INT IDENTITY (1, 1) NOT NULL,
[audi_id_first] NVARCHAR (20) NULL,
[audi_id_second] NVARCHAR (20) NULL,
[audi_by] NVARCHAR (100) NOT NULL,
[audi_on] DATETIME NOT NULL,
[audi_details] XML NULL,
[tabn_code] CHAR (4) NULL,
[audt_id] INT NOT NULL,
CONSTRAINT [PK_dbo.' + @tableName + '] PRIMARY KEY CLUSTERED ([audi_id] ASC),
CONSTRAINT [FK_dbo.' + @tableName + '_dbo.tabn_table_name_tabn_code] FOREIGN KEY ([tabn_code]) REFERENCES [dbo].[tabn_table_name] ([tabn_code]),
CONSTRAINT [FK_dbo.' + @tableName + '_dbo.audt_audit_type_audt_id] FOREIGN KEY ([audt_id]) REFERENCES [dbo].[audt_audit_type] ([audt_id])
)'
EXEC sp_executesql @createSql
END
END
在数据库初始化时,确保表存在:
public class AuditInitialiser : IDatabaseInitializer<AuditContext>
{
public void InitializeDatabase(AuditContext context)
{
if (context.Database.CreateIfNotExists())
{
Seed(context);
}
var tableName = new SqlParameter("@tableName", SqlDbType.Char);
tableName.Value = context.AuditTableName;
context.Database.ExecuteSqlCommand("EXEC CreateAuditTableIfNoneExists @tableName", tableName);
}
公共类审核初始化器:IDatabaseInitializer
{
public void InitializeDatabase(AuditContext上下文)
{
if(context.Database.CreateIfNotExists())
{
种子(上下文);
}
var tableName=新的SqlParameter(“@tableName”,SqlDbType.Char);
tableName.Value=context.AuditTableName;
context.Database.ExecuteSqlCommand(“EXEC CreateAuditTableIfNoneExists@tableName”,tableName);
}
但是,这只适用于我,因为我使用的是API,所以是无状态的,每次都构造DbContext。这确保了表始终存在。如果我在指定的系统上工作,则不起作用。我不太喜欢存储过程,但在这种情况下,可能需要使用EF 6(EF5??)的绑定到存储进程的能力。然后可以将表作为参数传递。请查看这是否有帮助:
(您也可以使用EntitySQL来解决此问题)存储过程似乎映射为插入、更新和删除,而不是读取。我的理解是否正确?如果我这样做,我将无法返回数据?假设我可以执行原始SQL查询以获取数据。我相信您可以使用存储过程执行选择(支持返回多个结果集的过程是EF 5的一项功能,因此必须支持选择)。但我自己没有这样做。首先,我很难实际添加存储过程。我是先编写代码的。如果没有sql server manager,我如何将过程添加到数据库中?谢谢。我通常不使用迁移(不是针对它们,只是不适合我们的工作流程)。我通常会使用sql server manager。但是,请看一下:
public class AuditInitialiser : IDatabaseInitializer<AuditContext>
{
public void InitializeDatabase(AuditContext context)
{
if (context.Database.CreateIfNotExists())
{
Seed(context);
}
var tableName = new SqlParameter("@tableName", SqlDbType.Char);
tableName.Value = context.AuditTableName;
context.Database.ExecuteSqlCommand("EXEC CreateAuditTableIfNoneExists @tableName", tableName);
}