나는 이것을 보았다 :
엔티티 프레임 워크 4.x에서 테이블을 어떻게 동적으로 선택할 수 있습니까?
그러나 내 상황에서는 기본 클래스를 사용할 수 없습니다. 감사를 위해 사용자 그룹과 주별 테이블을 생성하려고하므로 런타임에 생성되기 전에 무엇이 호출되는지 알 수 없습니다.
따라서 연중 첫 주에 로그인하면 다음과 같습니다.
Group1_01_2014
이것이 가능한가? 생성시 데이터베이스 이름을 변경하려고했지만 데이터베이스 마이그레이션에 대한 표준 예외가 발생합니다.
감사.
편집 : 누군가 데이터베이스 분할이 어리 석다고 말하기 전에 내가 많이 감사하고 있음을 알고 있습니다. 아이디어는 성능에 심각한 영향을주지 않고 대부분의 트랜잭션을 감사하고 필요한만큼 오래 저장할 수 있도록하는 것입니다.
편집 2 : 누군가가 더 나은 해결책을 가지고 있다면 나는 모두 귀를 기울입니다.
해결책
저장 프로 시저를 사용하여 끝났습니다.
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 #에서 이것을 호출합니다.
public void AddRecord(Audit record)
{
var Id1 = new SqlParameter("@audi_id_first", SqlDbType.NVarChar);
Id1.Value = (object)record.Id1 ?? System.DBNull.Value;
var Id2 = new SqlParameter("@audi_id_second", SqlDbType.NVarChar);
Id2.Value = (object)record.Id2 ?? System.DBNull.Value;
var UserName = new SqlParameter("@audi_by", SqlDbType.NVarChar);
UserName.Value = record.UserName;
var Stamp = new SqlParameter("@audi_on", SqlDbType.DateTime);
Stamp.Value = record.Stamp;
var Details = new SqlParameter("@audi_details", SqlDbType.Xml);
Details.Value = (object)record.Details ?? System.DBNull.Value;
var TableCode = new SqlParameter("@tabn_code", SqlDbType.Char);
TableCode.Value = record.TableCode;
var TypeId = new SqlParameter("@audt_id", SqlDbType.Int);
TypeId.Value = record.TypeId;
var DatabaseCode = new SqlParameter("@audi_db_code", SqlDbType.Char);
DatabaseCode.Value = CallingPrefix;
this.Database.ExecuteSqlCommand("EXEC Audit_Insert @audi_id_first, @audi_id_second, @audi_by, @audi_on, @audi_details, @tabn_code, @audt_id, @audi_db_code",
Id1, Id2, UserName, Stamp, Details, TableCode, TypeId, DatabaseCode);
}
내 다음 투쟁은 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);
}
그러나 이것은 API를 사용하고 있기 때문에 저에게만 작동하므로 상태 비 저장이며 매번 DbContext를 생성합니다. 이렇게하면 테이블이 항상 존재합니다. 명시된 시스템에서 작업을 수행하면 작동하지 않습니다.
저는 저장 프로 시저를 좋아하지는 않지만 EF 6 (EF5 ??)의 저장 프로 시저 바인딩 기능을 사용하려는 경우가 될 수 있습니다. 그런 다음 매개 변수로 사용할 테이블을 전달할 수 있습니다. 이것이 도움이되는지 확인하십시오 : Entity Framework 6 (Code-First)에서 저장 프로 시저를 호출하는 방법?
(이 문제를 해결하기 위해 EntitySQL을 사용할 수도 있습니다)
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다