0

Acck 現在のバージョンの前に、エンティティ クラス用の特別なストアド プロシージャをしばらく作成する必要はありませんでした。そして、それは小さなテーブルにありました。削除を作成しましたが、EF では挿入と更新も作成する必要があることを忘れていました。これを行う簡単な方法を知っている人はいますか?タイピングを楽しみにせずに、これを行う必要があるそれぞれに約30〜50列の約7〜8個のテーブルがあります。

4

2 に答える 2

1

そして、それは小さなテーブルにありました。削除を作成しましたが、EF では挿入と更新も作成する必要があることを忘れていました

この質問で EntityFramework 5.0 にタグを付けたので、なぜ削除のためにストアド プロシージャを生成する必要があるのか​​ よくわかりません。

すべての CRUD (作成、読み取り、削除、更新) は DbContext で行われ、そのための手順を記述する必要はありません。よく整理されたデータベース (PK、FK、適切なインデックスを含む) がある場合は、EF のビューをコンパイルしてさらに良い結果を得ることができるため、ストアド プロシージャを用意する必要はありません。

サンプル コードを参照してください。

    DbContext context = new YourContext();

    public bool Delete<TEntity>(TEntity entity) where TEntity : class
    {
        var set = context.Set<TEntity>();
        set.Attach(entity);
        return true;
    }

    public bool Add<TEntity>(TEntity entity) where TEntity : class
    {
        var set = context.Set<TEntity>();
        set.Add(entity);
        return true;
    }

このアプローチを使用する必要さえありません。次の例のように、DbContext.Set を直接使用できます。

    void Run()
    {

        using (DbContext context = new MyContext())
        {
            //Create a new person to insert
            var newItem = new Person() { Name = "Mike"} ;

            var set = context.Set<Person>();
            set.Add(newItem);

            // Returns a record from database with PK = "John"
            var itemToDelete = set.Find("John");
            set.Remove(itemToDelete);

            // This will add the new record, and delete "John" from the Database
            context.SaveChanges();
        }
    }

ご覧のとおり、CRUD のストアド プロシージャは必要ありません。

データベースに関連する他のものにはストアドプロシージャを使用します.EFでは必要ありません:)

これを行う簡単な方法を知っている人はいますか?タイピングを楽しみにせずに、これを行う必要があるそれぞれに約30〜50列の約7〜8個のテーブルがあります。

ここでの要点は、EF を使用する場合、CRUD 操作を処理するためにストアド プロシージャを記述する必要がないことを示すことでした。

あなたはこれを行う簡単な方法を求めました(そして、それらを入力したくないとさえ言いました)私の答えは次のとおりです。

手っ取り早い方法は、何も手続きをしないことです!これは高速で、入力を避けることができます! :)

示されているコードは、ストアド プロシージャを必要とせずに要件を既に処理しています。:)

追加情報

ストアド プロシージャを削除する必要があると考える理由が、関連するエンティティを削除したいためであり、EF がこの状況を処理しないと考えている場合、これは別の問題であり、いくつかの考えられる原因を教えてくれるかもしれません。

1) FK 参照のためにエラーで終了する場合があります。この場合は、こちらをご覧ください

2)他のエンティティとの関係から1つのエンティティを削除するときに、EFがレコードを物理的に削除したいことを理解できないため、.ChangeStateを削除済みに明示的に変更する必要があるため、エラーが発生する可能性があります。

次の例を見てください。

public static void StudentLeaves(string name)
{
    using (var context = new SchoolContext())
    {
        context.Students.Remove(context.Students.Single(s => s.Name == name));
        context.SaveChanges();
    }
}

上記の例は、この生徒を削除しますよね? しかし、今2番目の例を見てください

public static void StudantLeaveParticularSchool(string schoolName, string name)
{
    using (var context = new SchoolContext())
    {
        var school = context.Schools.Single(a => a.Nome == schoolName);
        school .Students.Remove(context.Students.Single(a => a.Nome == name));
        context.SaveChanges();
    }
}

次のコードは、 Student を Database から削除するのではなく、関係を削除するだけです!

CodeFirst を使用している場合は、次のように、DeleteCascade を使用することを明示的に指定できます。

modelBuilder
    .Entity()
    .HasRequired(s => s.Schools)
    .WithMany(r => r.Students)
.WillCascadeOnDelete();

更新しました:

ストアド プロシージャを作成する "魔法の" 方法に興味がある方のために、その方法を説明しますが、もう一度言います: ベスト プラクティスで EF を使用している場合は、その必要はありません。 EF を使用して最初に開発を始めたとき、これが必要だと思ったので、数百のストアド プロシージャを瞬く間に生成するいくつかの T4 ファイルを作成しました。しかし、しばらくして、これは EF を使用する場合の正しいアプローチではないことが判明したため、手順を削除し、T4 をプロジェクトから除外したことで、事態ははるかに簡単になりました。

プロシージャを作成するには、T4 ファイルを作成する必要があります。T4 の詳細については、こちら ( http://msdn.microsoft.com/en-us/library/vstudio/bb126247.aspx )を参照してください。

私たちが作成した DELETE 作成 T4 テンプレートをお見せします (これを実行するには、他のベース .tt ファイルが必要になるため、これはサンプルであることを覚えておいてください)。

<#@ template language="C#" debug="true" #>
<#@ output extension=".sql" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.XML" #>
<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>
<#@ assembly name="Microsoft.SqlServer.Management.Sdk.Sfc" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
<#@ import namespace="Microsoft.SqlServer.Management.Common" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
-- Winsys Solutions
-- Stored Procedure de delete para a tabela <#= this.SchemaName #>.<#= this.TableName #>
CREATE PROCEDURE <#= this.SchemaName #>.<#= this.TableName.Replace("TBWS4_", "PRWS4_") #>_Delete
    <# WriteParameterDeclarations(this.Table); #> 
AS
BEGIN
    DELETE FROM 
        <#= this.SchemaName #>.<#= this.TableName #> 
    WHERE
        <# WriteWhereClause(this.Table); #> 
END
GO
<#@ include file="CommonSqlHelper.tt" #>

<#+
    /// <summary>
    /// Writes stored procedure parameter declarations for all columns in the 
    /// primary key and all TIMESTAMP columns of the specified table. 
    /// </summary>
    void WriteParameterDeclarations(Table table)
    {
        PushIndent("    ");
        int parameterIndex = 0;
        foreach(Column column in table.Columns)
        {
            if (column.InPrimaryKey || column.DataType.SqlDataType == SqlDataType.Timestamp)
            {
                if (parameterIndex > 0)
                    WriteLine(",");
                Write("@{0} {1}", column.Name, GetDataTypeDeclaration(column.DataType));
                parameterIndex++;
            }
        }
        PopIndent();
    }
#>

<#+
    string TableName
    {
        get { return (string) CallContext.GetData("DeleteStoredProcedure.TableName"); }
    }

    string SchemaName
    {
        get { return (string) CallContext.GetData("DeleteStoredProcedure.SchemaName"); }
    }

    Table Table
    {
        get { return (Table) CallContext.GetData("DeleteStoredProcedure.Table"); }
    }
#>

ヘルパー メソッドは次のとおりです。

/// <summary>
/// Returns a string that contains T-SQL declaration for the specified data 
/// type. For string data types this includes maximum length, for numeric 
/// data types this includes scale and precision.
/// </summary>
string GetDataTypeDeclaration(DataType dataType)
{
    string result = dataType.Name;
    switch(dataType.SqlDataType)
    {
        case SqlDataType.Binary:
        case SqlDataType.Char:
        case SqlDataType.NChar:
        case SqlDataType.NVarChar:
        case SqlDataType.VarBinary:
        case SqlDataType.VarChar:
            result += string.Format("({0})", dataType.MaximumLength);
            break;

        case SqlDataType.NVarCharMax:
        case SqlDataType.VarBinaryMax:
        case SqlDataType.VarCharMax:
            result += "(max)";
            break;

        case SqlDataType.Decimal:
        case SqlDataType.Numeric:
            result += string.Format("({0}, {1})", dataType.NumericPrecision, dataType.NumericScale);
            break;
    }
    return result;
}

/// <summary>
/// Generates where clause for UPDATE and DELETE statements for the specified
/// table.
/// </summary>
void WriteWhereClause(Table table, bool includeAllColumns = false)
{
    PushIndent("        ");
    int whereIndex = 0;
    foreach(Column column in table.Columns)
    {
        if (column.InPrimaryKey || column.DataType.SqlDataType == SqlDataType.Timestamp || includeAllColumns)
        {
            if (whereIndex > 0)
                WriteLine(" AND");

            if (includeAllColumns)
                Write("({0} = @{0} OR @{0} IS NULL)", column.Name);
            else
                Write("{0} = @{0}", column.Name);

            whereIndex++;           
        }
    }
    PopIndent();
}
于 2013-05-15T21:43:20.710 に答える