2012-05-16 12 views
7

Io uso codefirst e io uso Elmah. Ho ricreato ogni volta che il database, è necessario aggiungere manualmente il codice dal file:Come aggiungere il codice per inizializzare il database 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 

eseguo questo codice automaticamente? Ho cercato di usare db.Database.ExecuteSqlCommand ma ho un sacco di errori di forma:

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

sarebbe un grosso problema spostare l'elmah db in un db separato ??in questo modo, non hai il fastidio di perdere tutti gli eventi registrati ogni volta pure. semplice come aggiungere una connessione aggiuntiva nel web.config –

+0

elmah è solo la parte superiore dell'iceberg. Ho altri script per i database statici. – Mediator

+0

ok, credo che quello che sto dicendo è che sicuramente la migliore pratica qui sarebbe che solo il tuo codice prima db è influenzato da tutto questo (cioè ricreazione del db sul cambio del modello). tutte le altre tabelle non correlate a questo devono trovarsi in un db ApplicationServices o simile. questo è certamente come lo facciamo nel nostro negozio. –

risposta

18

Provate questa migrazione, tenendo presente che si aspetta che tutte le istruzioni GO siano su una singola riga e che il file utilizzi \ r \ n terminazioni di riga. Ho installato Elmah utilizzando il pacchetto elmah.sqlserver NuGet, che rilascia il file SqlServer.sql nella posizione appropriata. Dovrai cambiare il nome della risorsa per abbinare il tuo progetto.

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

ho

+1

Per far funzionare tutto questo ho avuto bisogno di cambiare l'azione di build dello script su "Embedded Resource", come descritto qui: http://stackoverflow.com/questions/3068736/cant-load-a-manifest- resource-with-getmanifestresourcestream Ottima risposta, grazie. –

+0

Come posso aggiornare il DB con questa nuova migrazione creata manualmente? Quando eseguo 'update-database', ottengo questo: "La migrazione target specificata 'Elmah' non esiste.Assicurarsi che la migrazione target si riferisca a un ID di migrazione esistente" – ofirbt

+0

Ho usato solo una stringa con SQL (quindi non l'ho messo in un file separato). Rimosso il \ r \ n e sta funzionando alla grande. Grazie molto. – ssanchezz23

0

Si tratta di una serie di comandi SQL separati da dichiarazioni GO (che non sono strettamente i comandi T-SQL)

È possibile utilizzare SQL Managment Studio per eseguire lo script o lo strumento della riga di comando SQLCMD.exe

0

Non penso che sia necessario eseguire molti batch su ExecuteSqlCommand.

Perché non lo si esegue semplicemente su SSMS?

+0

Non ho capito cos'hai – Mediator

0

Avrete bisogno di analizzare il vostro script, dividerlo per separare i comandi SQL ed eseguire ognuno di essi individualmente tramite SqlCommand. Sfortunatamente, non sono a conoscenza di un modo per automatizzare questo.

0

Lo script richiede la separazione dei batch (GO è il separatore batch) e invia ciascun batch individualmente a SQL Server. In realtà ho un progetto di esempio dbutilsqlcmd che fa proprio questo, e supporta anche più estensioni sqlcmd come :setvar e $(variable) sostituzione nello script, che può essere abbastanza utile alla distribuzione.

4

solo per formalizzare il mio commento all'OP come risposta;

Penso che la migliore pratica qui sarebbe che solo il tuo codice prima db dovrebbe essere influenzato da eventuali cambiamenti radicali (ad esempio ricreazione del db sul cambio del modello). Tutte le altre tabelle non correlate a questo devono trovarsi in un db ApplicationServices o simile e NON nel core db. In questo modo non crei un incubo di supporto ogni volta che devi aggiornare il tuo modello con una semplice proprietà o una modifica del tipo di dati. Inoltre, si finisce per perdere l'intera cronologia delle tabelle di registrazione (e di altre) DB ogni volta che si apporta una modifica.

Quindi, in una parola, penso che stai affrontando il problema sbagliato con una soluzione potenzialmente inappropriata.

Questo è certamente il modo in cui lo facciamo nel nostro negozio e nei progetti precedenti su cui ho lavorato.

+0

cheers denis !! :) avere un week-end per il weekend –

0

V'è ora un pacchetto NuGet che inizializzare la tabella Elmah e procs per voi: https://www.nuget.org/packages/Elmah.SqlServer.EFInitializer/. Aggiungilo al tuo progetto web. Utilizzerà quindi il codice EF per crearlo per te. Aggiunge un inizializzatore alla tua cartella App_Start in modo che tu non debba aggiungere alcun codice. Aggiungerà una migrazione al tuo database per assicurarti che venga aggiunto solo una volta.

Problemi correlati