2012-05-16 10 views
7

私はcodefirstを使用していますが、私はElmahを使用します。SQLデータベースを初期化するコードを追加する方法

/* 

    ELMAH - Error Logging Modules and Handlers for ASP.NET 
    Copyright (c) 2004-9 Atif Aziz. All rights reserved. 

    Author(s): 

     Atif Aziz, http://www.raboof.com 
     Phil Haacked, http://haacked.com 

    Licensed under the Apache License, Version 2.0 (the "License"); 
    you may not use this file except in compliance with the License. 
    You may obtain a copy of the License at 

     http://www.apache.org/licenses/LICENSE-2.0 

    Unless required by applicable law or agreed to in writing, software 
    distributed under the License is distributed on an "AS IS" BASIS, 
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    See the License for the specific language governing permissions and 
    limitations under the License. 

*/ 

-- ELMAH DDL script for Microsoft SQL Server 2000 or later. 

-- $Id: SQLServer.sql 677 2009-09-29 18:02:39Z azizatif $ 

DECLARE @DBCompatibilityLevel INT 
DECLARE @DBCompatibilityLevelMajor INT 
DECLARE @DBCompatibilityLevelMinor INT 

SELECT 
    @DBCompatibilityLevel = cmptlevel 
FROM 
    master.dbo.sysdatabases 
WHERE 
    name = DB_NAME() 

IF @DBCompatibilityLevel <> 80 
BEGIN 

    SELECT @DBCompatibilityLevelMajor = @DBCompatibilityLevel/10, 
      @DBCompatibilityLevelMinor = @DBCompatibilityLevel % 10 

    PRINT N' 
    =========================================================================== 
    WARNING! 
    --------------------------------------------------------------------------- 

    This script is designed for Microsoft SQL Server 2000 (8.0) but your 
    database is set up for compatibility with version ' 
    + CAST(@DBCompatibilityLevelMajor AS NVARCHAR(80)) 
    + N'.' 
    + CAST(@DBCompatibilityLevelMinor AS NVARCHAR(80)) 
    + N'. Although 
    the script should work with later versions of Microsoft SQL Server, 
    you can ensure compatibility by executing the following statement: 

    ALTER DATABASE [' 
    + DB_NAME() 
    + N'] 
    SET COMPATIBILITY_LEVEL = 80 

    If you are hosting ELMAH in the same database as your application 
    database and do not wish to change the compatibility option then you 
    should create a separate database to host ELMAH where you can set the 
    compatibility level more freely. 

    If you continue with the current setup, please report any compatibility 
    issues you encounter over at: 

    http://code.google.com/p/elmah/issues/list 

    =========================================================================== 
' 
END 
GO 

/* ------------------------------------------------------------------------ 
     TABLES 
    ------------------------------------------------------------------------ */ 

CREATE TABLE [dbo].[ELMAH_Error] 
(
    [ErrorId]  UNIQUEIDENTIFIER NOT NULL, 
    [Application] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [Host]  NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [Type]  NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [Source]  NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [Message]  NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [User]  NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, 
    [StatusCode] INT NOT NULL, 
    [TimeUtc]  DATETIME NOT NULL, 
    [Sequence] INT IDENTITY (1, 1) NOT NULL, 
    [AllXml]  NTEXT COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
) 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[ELMAH_Error] WITH NOCHECK ADD 
    CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY NONCLUSTERED ([ErrorId]) ON [PRIMARY] 
GO 

ALTER TABLE [dbo].[ELMAH_Error] ADD 
    CONSTRAINT [DF_ELMAH_Error_ErrorId] DEFAULT (NEWID()) FOR [ErrorId] 
GO 

CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_App_Time_Seq] ON [dbo].[ELMAH_Error] 
(
    [Application] ASC, 
    [TimeUtc]  DESC, 
    [Sequence]  DESC 
) 
ON [PRIMARY] 
GO 

/* ------------------------------------------------------------------------ 
     STORED PROCEDURES              
    ------------------------------------------------------------------------ */ 

SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_NULLS ON 
GO 

CREATE PROCEDURE [dbo].[ELMAH_GetErrorXml] 
(
    @Application NVARCHAR(60), 
    @ErrorId UNIQUEIDENTIFIER 
) 
AS 

    SET NOCOUNT ON 

    SELECT 
     [AllXml] 
    FROM 
     [ELMAH_Error] 
    WHERE 
     [ErrorId] = @ErrorId 
    AND 
     [Application] = @Application 

GO 
SET QUOTED_IDENTIFIER OFF 
GO 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_NULLS ON 
GO 

CREATE PROCEDURE [dbo].[ELMAH_GetErrorsXml] 
(
    @Application NVARCHAR(60), 
    @PageIndex INT = 0, 
    @PageSize INT = 15, 
    @TotalCount INT OUTPUT 
) 
AS 

    SET NOCOUNT ON 

    DECLARE @FirstTimeUTC DATETIME 
    DECLARE @FirstSequence INT 
    DECLARE @StartRow INT 
    DECLARE @StartRowIndex INT 

    SELECT 
     @TotalCount = COUNT(1) 
    FROM 
     [ELMAH_Error] 
    WHERE 
     [Application] = @Application 

    -- Get the ID of the first error for the requested page 

    SET @StartRowIndex = @PageIndex * @PageSize + 1 

    IF @StartRowIndex <= @TotalCount 
    BEGIN 

     SET ROWCOUNT @StartRowIndex 

     SELECT 
      @FirstTimeUTC = [TimeUtc], 
      @FirstSequence = [Sequence] 
     FROM 
      [ELMAH_Error] 
     WHERE 
      [Application] = @Application 
     ORDER BY 
      [TimeUtc] DESC, 
      [Sequence] DESC 

    END 
    ELSE 
    BEGIN 

     SET @PageSize = 0 

    END 

    -- Now set the row count to the requested page size and get 
    -- all records below it for the pertaining application. 

    SET ROWCOUNT @PageSize 

    SELECT 
     errorId  = [ErrorId], 
     application = [Application], 
     host  = [Host], 
     type  = [Type], 
     source  = [Source], 
     message  = [Message], 
     [user]  = [User], 
     statusCode = [StatusCode], 
     time  = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z' 
    FROM 
     [ELMAH_Error] error 
    WHERE 
     [Application] = @Application 
    AND 
     [TimeUtc] <= @FirstTimeUTC 
    AND 
     [Sequence] <= @FirstSequence 
    ORDER BY 
     [TimeUtc] DESC, 
     [Sequence] DESC 
    FOR 
     XML AUTO 

GO 
SET QUOTED_IDENTIFIER OFF 
GO 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_NULLS ON 
GO 

CREATE PROCEDURE [dbo].[ELMAH_LogError] 
(
    @ErrorId UNIQUEIDENTIFIER, 
    @Application NVARCHAR(60), 
    @Host NVARCHAR(30), 
    @Type NVARCHAR(100), 
    @Source NVARCHAR(60), 
    @Message NVARCHAR(500), 
    @User NVARCHAR(50), 
    @AllXml NTEXT, 
    @StatusCode INT, 
    @TimeUtc DATETIME 
) 
AS 

    SET NOCOUNT ON 

    INSERT 
    INTO 
     [ELMAH_Error] 
     (
      [ErrorId], 
      [Application], 
      [Host], 
      [Type], 
      [Source], 
      [Message], 
      [User], 
      [AllXml], 
      [StatusCode], 
      [TimeUtc] 
     ) 
    VALUES 
     (
      @ErrorId, 
      @Application, 
      @Host, 
      @Type, 
      @Source, 
      @Message, 
      @User, 
      @AllXml, 
      @StatusCode, 
      @TimeUtc 
     ) 

GO 
SET QUOTED_IDENTIFIER OFF 
GO 
SET ANSI_NULLS ON 
GO 

私は、自動的にこのコードを実行します。 私は手動でファイルからのコードを追加する必要があり、たびに、データベースを再作成しましたか? 私はdb.Database.ExecuteSqlCommandを使用しようとしましたが、私は、フォームのエラーの多くを得る:

Incorrect syntax near 'GO'. 
Incorrect syntax near the keyword 'ALTER'. 
Incorrect syntax near the keyword 'ALTER'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near the keyword 'SET'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Must declare the scalar variable "@ErrorId". 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Must declare the scalar variable "@TotalCount". 
Must declare the scalar variable "@PageIndex". 
Must declare the scalar variable "@TotalCount". 
Must declare the scalar variable "@Application". 
Must declare the scalar variable "@PageSize". 
Must declare the scalar variable "@PageSize". 
Must declare the scalar variable "@Application". 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
Must declare the scalar variable "@ErrorId". 
Incorrect syntax near 'GO'. 
Incorrect syntax near 'GO'. 
+1

elmah dbを別のデータベースに移動するのは大変なことでしょうか?そうしたやり方では、毎回ログに記録された出来事をすべて失うという面倒なことはありません。 web.configに追加の接続文字列を追加するだけで簡単です –

+0

elmahは氷山の一番上にあります。私は静的データベースのための他のスクリプトを持っています。 – Mediator

+0

私が言っていることは、確かにベストプラクティスは、あなたのコードの最初のdbだけがこのすべて(つまり、モデルの変更時のdbの再作成)の影響を受けるということです。それと無関係の他のすべてのテーブルは、ApplicationServices dbまたはそれに類するものでなければなりません。これは確かに私たちの店でそれを行う方法です。 –

答えて

18

すべてのGO文が1行にあり、ファイルが\ r \ n行末を使用することを前提にして、この移行を試してください。 elmah.sqlserver NuGetパッケージを使用してElmahをインストールしました。これは、SqlServer.sqlファイルを適切な場所にドロップします。プロジェクトに合うようにリソース名を変更する必要があります。

public partial class Elmah : DbMigration 
{ 
    public override void Up() 
    { 
     var sqlStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyProject.App_Readme.Elmah.SqlServer.sql"); 
     using(var sqlStreamReader = new StreamReader(sqlStream)) 
     { 
      string sqlScript = sqlStreamReader.ReadToEnd(); 
      ExecuteSqlScript(sqlScript); 
     } 
    } 

    void ExecuteSqlScript(string sqlScript) 
    { 
     string[] sql = sqlScript.Split(new[] {"\r\nGO\r\n"}, StringSplitOptions.RemoveEmptyEntries); 

     foreach (var sqlCommand in sql) 
     { 
      if (!string.IsNullOrWhiteSpace(sqlCommand)) 
       Sql(sqlCommand); 
     } 
    } 

    public override void Down() 
    { 
     DropTable("ELMAH_Error"); 
     Sql("DROP PROCEDURE ELMAH_GetErrorXml"); 
     Sql("DROP PROCEDURE ELMAH_GetErrorsXml"); 
     Sql("DROP PROCEDURE ELMAH_LogError"); 
    } 
} 

I

+1

これを動作させるには、スクリプトのビルドアクションを "組み込みリソース"に変更する必要がありました。ここで説明します:http://stackoverflow.com/questions/3068736/cant-load-a-manifest- resource-with-getmanifestresourcestream素晴らしい答えですが、ありがとうございます。 –

+0

この手動で作成した新しい移行を使用してDBを更新するにはどうすればよいですか? "update-database"を実行すると、 "指定したターゲット移行 'Elmah'が存在しません。ターゲット移行が既存の移行IDを参照していることを確認してください。" – ofirbt

+0

SQLで文字列のみを使用しましたそれは別のファイルにあります)。 \ r \ nを削除して、うまくいきます。どうもありがとう。 – ssanchezz23

0

これは(厳密にT-SQLコマンドではありません)GOステートメントで区切られたSQLコマンドの一連の

あなたですSQL Managment Studioを使用してスクリプトを実行するか、コマンドラインツールSQLCMD.exe

0

ExecuteSqlCommandでそのバッチを実行する必要はありません。

なぜあなたは単にSSMSでそれを実行しませんか?

+0

私はあなたが何を理解していません – Mediator

0

スクリプトを解析し、それを分割してSQLコマンドを分離し、それぞれをSqlCommandを通して個別に実行する必要があります。残念ながら、私はこれを自動化する方法を知らない。

0

このスクリプトでは、バッチを区切る必要があります(GOはバッチ区切りです)、各バッチを個別にSQL Serverに送信する必要があります。私は実際にそのようなサンプルプロジェクトdbutilsqlcmdを持っていますが、スクリプトでは:setvar$(variable)のようなsqlcmd拡張機能の置き換えをサポートしています。

4

答えとしてOPに私のコメントを正式にするために。

ここでのベストプラクティスは、コードの最初のdbだけが根本的な変更(モデルの変更時のdbの再作成)の影響を受けることになると考えています。関係のない他のすべてのテーブルは、ApplicationServices dbまたはそれに類するものであり、コアdbではありません。そうすれば、簡単なプロパティまたはデータ型の変更でモデルを更新する必要があるたびに、サポートの悪夢を作成することはありません。さらに、変更するたびに、ロギング(およびその他の)dbテーブルの全履歴を失うことになります。

言い換えれば、間違った解決策を間違った問題に取り組んでいると思います。

これは当店でやっていることであり、私がこれまで取り組んでいた以前のプロジェクトでもそうです。

+0

歓声デニス! :) grt weekendを持っています –

0

あなたのためのELMAHテーブルとprocsのを初期化しますnugetパッケージなりました:https://www.nuget.org/packages/Elmah.SqlServer.EFInitializer/が。 Webプロジェクトに追加します。その後、EFコードを使用して作成します。 App_StartフォルダにInitializerを追加するので、実際にコードを追加する必要はありません。データベースへの移行が追加され、確実に一度だけ追加されます。

関連する問題