使用Entity Framework时规范化SQL表

时间:2016-07-21 00:16:01

标签: c# sql-server entity-framework

首先让我说我不是SQL专家,新手是合适的

我有一个目前有1000万行的日志表:

Logs( Id, FKId, Source, Message )

我想知道为源和消息规范化我的表是否有益。在10米行中,只有200,000个DISTINCT源和100万个不同的消息。为了规范化这些数据,我假设我还需要两个表。带有Id和文本的源,带有Id和Text的消息(或者它们可能是同一个表?)

我目前正在使用Entity Framework来插入行。我想知道实体框架将如何处理这个问题,如果我得到性能提升,我正在寻找,特别是在尝试做“消息LIKE'%error%'”时,或者只是通常使整个事情变小,从而减少分页

我认为如果新插入的消息是唯一的,EF将无法自动为我找出,所以我必须事先弄明白,或者通过存储过程进行插入。如果我每天在这个表上做200万次插入,那么通过EF调用SP会如何改变性能

context.Logs.Add(log)
context.Save();

1 个答案:

答案 0 :(得分:2)

我认为你的C#代码会有这样的方法签名:

public void AddLogMessage(Int32 foreignKeyId, String source, String message)

如果您将数据库设计修改为:

Logs( LogId, FKId, SourceId, MessageId )
Sources( SourceId, Value )
Messages( MessageId, Value )
-- with all appropriate FK constraints on Logs->Sources and Logs->Messages

...然后你会发现自己编写的C#/ Linq比查找源和消息文本所需的更多,并将它们放入记录中(除了使用更多的数据库聊天)。实际上,这最好使用存储过程来完成,您将作为函数导入添加到DBContext:

CREATE PROCEDURE AddLogMessage
    @fkId int,
    @source nvarchar(255),
    @message nvarchar(1024)
AS
BEGIN
    SET NOCOUNT ON

    BEGIN TRANSACTION

    DECLARE @sourceId int = SELECT SourceId FROM Sources WHERE Value = @source
    IF @sourceId IS NULL
    BEGIN
        INSERT INTO Sources ( Value ) VALUES ( @source )
        SET @sourceId = SELECT SCOPE_IDENTITY()
    END

    DECLARE @messageId int = SELECT MessageId FROM Messages WHERE Value = @message
    IF @messageId IS NULL
    BEGIN
        INSERT INTO Messages ( Value ) VALUES ( @message)
        SET @messageId = SELECT SCOPE_IDENTITY()
    END

    INSERT INTO Logs ( @fkId, @sourceId, @messageId )

    COMMIT TRANSACTION

END

将其导入DBContext后,只需像调用其他函数一样调用它:

public void AddLogMessage(Int32 foreignKeyId, String source, String message) {
    this.dbContext.AddLogMessage( foreignkeyId, source, message );
}