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);
    }