web-dev-qa-db-ja.com

エンティティフレームワークでネイティブSQLを実行することは可能ですか?

テーブル内のXMLフィールドを検索しようとしていますが、これはEFではサポートされていません。

純粋なAdo.netを使用しなくても、EFでネイティブSQLをサポートできますか?

65
user80855

.NET Frameworkバージョン4以降の場合:クエリが結果を返さない場合は ObjectContext.ExecuteStoreCommand() を使用し、 ObjectContext.ExecuteStoreQuery クエリが結果を返す場合。

以前のバージョンの.NET Frameworkの場合、何をすべきかを示すサンプルがあります。クエリが結果を返す場合、必要に応じてExecuteNonQuery()を置き換えます。

static void ExecuteSql(ObjectContext c, string sql)
{
    var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
    DbConnection conn = entityConnection.StoreConnection;
    ConnectionState initialState = conn.State;
    try
    {
        if (initialState != ConnectionState.Open)
            conn.Open();  // open connection if not already open
        using (DbCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = sql;
            cmd.ExecuteNonQuery();
        }
    }
    finally
    {
        if (initialState != ConnectionState.Open)
            conn.Close(); // only close connection if not initially open
    }
}
72
Justin Grant

Entity Framework 5.0を使用すると、 ExecuteSqlCommand を使用して、複数行/複数コマンドの純粋なSQLステートメントを実行できます。この方法では、メソッドがint(コマンドの実行後にデータベースによって返される結果)を返すため、戻り値を格納するためのバッキングオブジェクトを提供する必要はありません。

サンプル:

context.Database.ExecuteSqlCommand(@
"-- Script Date: 10/1/2012 3:34 PM  - Generated by ExportSqlCe version 3.5.2.18
SET IDENTITY_INSERT [Students] ON;

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (12,N'First Name',N'SecondName',{ts '1988-03-02 00:00:00.000'},N'RUA 19 A, 60',N'MORADA DO VALE',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3346-7125',NULL,NULL,{ts '2011-06-04 21:25:26.000'},2,1);

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (13,N'FirstName',N'LastName',{ts '1976-04-12 00:00:00.000'},N'RUA 201, 2231',N'RECANTO FELIZ',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3341-6892',NULL,NULL,{ts '2011-06-04 21:38:38.000'},2,1);
");

詳細については、こちらをご覧ください: Entity Framework Code First:データベース作成時にSQLファイルを実行する

24

Entity Framework 5の場合context.Database.SqlQuery

そしてEntity Framework 4context.ExecuteStoreQuery次のコード:

 public string BuyerSequenceNumberMax(int buyerId)
    {
        string sequenceMaxQuery = "SELECT TOP(1) btitosal.BuyerSequenceNumber FROM BuyerTakenItemToSale btitosal " +
                                  "WHERE btitosal.BuyerID =  " + buyerId +
                                  "ORDER BY  CONVERT(INT,SUBSTRING(btitosal.BuyerSequenceNumber,7, LEN(btitosal.BuyerSequenceNumber))) DESC";

        var sequenceQueryResult = context.Database.SqlQuery<string>(sequenceMaxQuery).FirstOrDefault();

        string buyerSequenceNumber = string.Empty;

        if (sequenceQueryResult != null)
        {
            buyerSequenceNumber = sequenceQueryResult.ToString();
        }

        return buyerSequenceNumber;
    }

リストを返すには、次のコードを使用します。

 public List<PanelSerialList> PanelSerialByLocationAndStock(string locationCode, byte storeLocation, string itemCategory, string itemCapacity, byte agreementType, string packageCode)
 {
       string panelSerialByLocationAndStockQuery = "SELECT isws.ItemSerialNo,  im.ItemModel " +
        "FROM Inv_ItemMaster im   " +
        "INNER JOIN  " +
        "Inv_ItemStockWithSerialNoByLocation isws  " +
        "   ON im.ItemCode = isws.ItemCode   " +
        "       WHERE isws.LocationCode = '" + locationCode + "' AND  " +
        "   isws.StoreLocation = " + storeLocation + " AND  " +
        "   isws.IsAvailableInStore = 1 AND " +
        "   im.ItemCapacity = '" + itemCapacity + "' AND " +
        "   isws.ItemSerialNo NOT IN ( " +
        "           Select sp.PanelSerialNo From Special_SpecialPackagePriceForResale sp  " +
        "           Where sp.PackageCode = '" + packageCode + "' )";


    return context.Database.SqlQuery<PanelSerialList>(panelSerialByLocationAndStockQuery).ToList();


}
17

.NET 4以降では、 ExecuteStoreQuery メソッドを使用できます。

var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql);

ここで、myDBEntitiesはObjectContextから継承されます。

class MyClass
{
    /* You can change query to more complicated, e.g. with joins */
    public const string sql = @"select [MyTable].[MyField] from [MyTable]";
    public string MyField { get; set; }
}

MyTableはEFクラスではなく、実際のテーブル名であることに注意してください。

16

複雑にしないでおく

using (var context = new MyDBEntities())
{
    var m = context.ExecuteStoreQuery<MyDataObject>("Select * from Person", string.Empty);
    //Do anything you wonna do with 
    MessageBox.Show(m.Count().ToString());
}
3
ELTEE
public class RaptorRepository<T>
    where T : class
{
    public RaptorRepository()
        : this(new RaptorCoreEntities())
    {
    }

    public RaptorRepository(ObjectContext repositoryContext)
    {
        _repositoryContext = repositoryContext ?? new RaptorCoreEntities();
        _objectSet = repositoryContext.CreateObjectSet<T>();
    }

    private ObjectContext _repositoryContext;
    private ObjectSet<T> _objectSet;
    public ObjectSet<T> ObjectSet
    {
        get
        {
            return _objectSet;
        }
    }


    public void DeleteAll()
    {
        _repositoryContext
            .ExecuteStoreCommand("DELETE " + _objectSet.EntitySet.ElementType.Name);
    }
}
2
Nirosh

それでは、2017年にこのすべてについて私たちは何を言いますか? 80kの相談では、EFでSQL要求を実行することは多くの人がやりたいことであると示唆しています。しかし、なぜ?どんなメリットがありますか?

私の評判の20倍の第一人者であるジャスティンは、受け入れられた答えで、同等のADOコードのように行を探す静的メソッドを提供します。また、このメソッドのすべてのユーザーは、文字列メソッド(壊れやすい、テスト不能、SQLインジェクション)を使用してSQLを構築するため、クエリを実行時パラメーターと連結する必要があります。そしてそれらのどれも単体テストではありません。

他の回答には同じ欠点がありますが、それ以外は同じです。 SQLは二重引用符で囲まれています。 SQLインジェクションの機会は自由に散らばっています。尊敬する仲間、これは絶対に野avな行動です。これが生成されているC#である場合、フレーム戦争が発生します。この方法でHTMLを生成することも受け入れませんが、どういうわけかSQLには問題ありません。クエリパラメータは問題の主題ではないことを知っていますが、表示されているものをコピーして再利用します。ここでの回答は、人々が行っていることのモデルと遺言の両方です。

EFは私たちの脳を溶かしましたか? EFはSQLを使用したくないので、なぜEFを使用してSQLを実行するのですか。

SQLを使用してリレーショナルDBと通信したいのは、大人にとって健全で正常な衝動です。 QueryFirstは、これをインテリジェントに行う方法を示しています。テーブルのインテリセンスを使用して、入力時に検証された.sqlファイル内のsqlと列。 C#ラッパーはツールによって生成されるため、クエリはコードで検出可能になり、入力と結果にインテリセンスが使用されます。型について心配することなく、強力な型定義をエンドツーエンドで行えます。列名またはそのインデックスを覚えておく必要はありません。また、他にも多くの利点があります...連結する誘惑はremovedです。接続を誤って処理する可能性もあります。すべてのクエリとそれらにアクセスするコードは、開発データベースに対して継続的に統合テストされます。 DBのスキーマ変更は、アプリのコンパイルエラーとしてポップアップします。ラッパーで自己テストメソッドを生成することもできるので、電話が鳴るのを待つのではなく、既存の運用データベースに対してアプリの新しいバージョンをtestできます。まだ説得力が必要ですか?

免責事項:QueryFirstを書きました:-)

0
bbsimonbb