2012-06-05 2 views
8

데이터베이스 어딘가에 저장할 customquery를 실행해야하는데, datatable 또는 dataset으로 반환하고 열을 자동 생성하는 gridview에 바인딩해야합니다.엔티티 프레임 워크를 사용하여 사용자 정의 SQL을 실행 하시겠습니까?

내 모든 데이터 액세스 계층은 엔티티 프레임 워크와 완벽하게 작동하지만, 일부 특정 시나리오에 나는이 작업을 수행해야 내가 EF 어떻게 든 그것을 할 수 있다면

답변

8

를 내가 엔티티 프레임 워크와 ado.net을 결합해야하는지 궁금하거나 귀하의 목표가 ADO.NET 구조 (DataTable 또는 DataSet)를 반환하는 것이라면, 그냥 고전적인 ADO.NET을 사용하십시오. 엔티티 집합에 데이터를 바인딩 한 다음 DataTable 또는 DataSet을 직접 채우는 것보다 쉽습니다.

그러나 EntityFramework를 통해 사용자 지정 쿼리를 실행하는 데 정말로 관심이 있다면 ExecuteQuery을 살펴보십시오. SQL 쿼리를 실행하고 결과를 모델의 엔티티에 다시 매핑 할 수 있습니다. 그런 다음 IEnumerable 결과를 가져 와서 DataTable 또는 DataSet에 매핑하는 연습을해야합니다. 따라서 "원래의 ADO.NET 방식을 사용하여 좋은 결과를 얻었습니다."라는 나의 원래 대답.

16

법인을위한 프레임 워크 5 사용

context.Database.SqlQuery


그리고 법인을위한 프레임 워크 4 다음 코드를 사용

context.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 + "')"; 



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


} 
+7

을위한 시험 매개 변수는 SQL 주입 공격을 방지합니다. –

9

를 사용합니다.

var connection = (System.Data.SqlClient.SqlConnection) _db.Database.Connection; 

if (connection != null && connection.State == ConnectionState.Closed) 
{ 
    connection.Open(); 
} 

var dt = new DataTable(); 

using (var com = new System.Data.SqlClient.SqlDataAdapter("Select * from Table", connection)) 
{ 
    com.Fill(dt); 
} 

을 그리고 우리는 EF 연결을 사용하여 쿼리를 실행하는 DataAdapter 또는 다른 고전적인 방법을 사용할 수 있습니다 : 당신의 엔티티 프레임 워크 컨텍스트를 사용하여 SQL 연결을 가져옵니다.

동적으로 작업을 수행하고 엔터티에 매핑 할 수없는 경우 매우 유용합니다. 예를 들어 DataTable에서 물건을 얻을 수 있습니다.

위의 구문은 EF 5.0입니다.

2

EF6을 사용하고 어느 날 동적 SQL 문자열을 실행하고 DataTable을 얻는 방법이 필요했습니다. 첫째로 나는 DbContext.Database.ConnectionSqlConnection에 단순히 던지고 모든 일을했다. 테스트를 위해 작동했지만 애플리케이션이 깨졌습니다. 왜냐하면 우리가 사용하는 Glimpse는 DbConnection의 자체 구현을 Glimpse.Ado.AlternateType.GlimpseDbConnection 유형으로 주입하기 때문입니다. DbConnection과 독립적으로 작동하는 접근 방식이 필요합니다.마지막으로 나는 다음과 같은 코드로 끝낼 :

public class SqlDataProvider : ISqlDataProvider 
{ 
    private readonly DbContext _context; 

    public SqlDataProvider(DbContext context) 
    { 
     _context = context; 
    } 

    public DataTable GetDataTable(string sqlQuery) 
    { 
     try 
     { 
      DbProviderFactory factory = DbProviderFactories.GetFactory(_context.Database.Connection); 

      using (var cmd = factory.CreateCommand()) 
      { 
       cmd.CommandText = sqlQuery; 
       cmd.CommandType = CommandType.Text; 
       cmd.Connection = _context.Database.Connection; 
       using (var adapter = factory.CreateDataAdapter()) 
       { 
        adapter.SelectCommand = cmd; 

        var tb = new DataTable(); 
        adapter.Fill(tb); 
        return tb; 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new SqlExecutionException(string.Format("Error occurred during SQL query execution {0}", sqlQuery), ex); 
     } 
    } 

그리고 이것은 어떤 경우에 작동합니다 : 당신은 당신이 모든 입력을 소독 한하지 않도록 경우 DbContext.Database.Connection이 사용 SQL이 SqlConnectionGlimpse.Ado.AlternateType.GlimpseDbConnection

관련 문제