2016-02-25 18 views
19

एंटीटी फ्रेमवर्क कोर dbData.Database.SqlQuery<SomeModel> को हटाकर मुझे अपनी पूर्ण-पाठ खोज क्वेरी के लिए कच्ची SQL क्वेरी बनाने का कोई समाधान नहीं मिल रहा है जो टेबल डेटा और रैंक को वापस कर देगा।डीबीसेट के बिना कच्चे एसक्यूएल क्वेरी - एंटीटी फ्रेमवर्क कोर

एंटिटी फ्रेमवर्क कोर में कच्ची एसक्यूएल क्वेरी बनाने के लिए मैंने देखा एकमात्र तरीका dbData.Product.FromSql("SQL SCRIPT"); के माध्यम से है जो उपयोगी नहीं है क्योंकि मेरे पास कोई डीबीसेट नहीं है जो क्वेरी में वापस आने वाले रैंक को मैप करेगा।

कोई विचार ???

+8

मैं SqlQuery को बहुत याद करूँगा और मेरे डीबीकॉन्टेक्स्ट में कस्टम क्लास को मैप करना नहीं चाहता हूं, जब मुझे वास्तव में एक विशिष्ट उपयोग मामले के लिए एक साधारण डीटीओ की आवश्यकता होती है। मैंने इस सुविधा को ईएफ कोर में वापस जोड़ने का अनुरोध करने के लिए एक उपयोगकर्ता आवाज बनाई है कि अगर कोई इस सुविधा को वापस लेना चाहे तो कोई भी वोट दे सकता है: https: //data.uservoice।कॉम/मंच/72025-इकाई-ढांचे-सुविधा-सुझाव/सुझाव/13183638-ऐड-डीबीकॉनटेक्स्ट-डेटाबेस-एसक्लक्वायरी-टू-एंट्री-फ्रेमवायर –

+1

https://github.com/aspnet/EntityFramework/issues/1862 के अनुसार, अब यह ईएफ कोर 1.2 और/या 1.1.0-पूर्वावलोकन 1 –

उत्तर

15

ईएफ कोर में अब आप "मुक्त" कच्चे वर्ग को निष्पादित नहीं कर सकते हैं। आपको उस कक्षा के लिए एक पीओसीओ कक्षा और DbSet परिभाषित करने की आवश्यकता है। अपने मामले में आप रैंक परिभाषित करने के लिए की आवश्यकता होगी:

var ranks = DbContext.Ranks 
    .FromSql("SQL_SCRIPT OR STORED_PROCEDURE @p0,@p1,...etc", parameters) 
    .AsNoTracking().ToList(); 

यह निश्चित रूप से केवल पढ़ने के लिए किया जाएगा के रूप में यह .AsNoTracking() कॉल शामिल करने के लिए उपयोगी होगा।

+2

के लिए लक्षित है, इसलिए मुझे लगता है कि मुझे एक नई संपत्ति 'डीबीसेट रैंक {प्राप्त करने के लिए' डीबीकॉन्टेक्स्ट 'का विस्तार करना होगा। सेट; } '। लिनक के संदर्भ में अब इसका क्या प्रभाव होगा? आईई। अब हम 'DBContext.Rank.Where (i => i.key == 1) 'जैसे किसी कथन का उपयोग करने में सक्षम नहीं होंगे, और क्या इस कथन में SQL में कोई कार्यान्वयन नहीं होगा और इसलिए विफल हो जाएगा? –

+0

इस सेट के खिलाफ उत्सर्जित लिंक को स्मृति में हल किया जाना है। यदि आपको विभिन्न WHERE वर्ग खंड को उत्सर्जित करने की आवश्यकता है तो आपको उन्हें पैरामीटर के रूप में शामिल करना होगा या एक अलग स्क्रिप्ट बनाना होगा। –

+0

मेरा डीबीसेट में "FromSql" विधि नहीं है। क्या यह एक विस्तार है जिसे मैं याद कर रहा हूं? – birwin

8

आप ईएफ कोर में कच्चे एसक्यूएल निष्पादित कर सकते हैं - इस कक्षा को अपनी परियोजना में जोड़ें। यह आपको कच्चे एसक्यूएल निष्पादित करने और पीओसीओ और डीबीएसईटी को परिभाषित किए बिना कच्चे नतीजे प्राप्त करने की अनुमति देगा। मूल उदाहरण के लिए https://github.com/aspnet/EntityFramework/issues/1862#issuecomment-220787464 देखें। ,

// Execute a query. 
using(var dr = await db.Database.ExecuteSqlQueryAsync("SELECT ID, Credits, LoginDate FROM SamplePlayer WHERE " + 
                  "Name IN ('Electro', 'Nitro')")) 
{ 
    // Output rows. 
    var reader = dr.DbDataReader; 
    while (reader.Read()) 
    { 
     Console.Write("{0}\t{1}\t{2} \n", reader[0], reader[1], reader[2]); 
    } 
} 
2

अभी के लिए जब तक वहाँ कुछ मैं एक कमांड का इस्तेमाल किया और इसे मैन्युअल रूप से नक्शा

using (var command = this.DbContext.Database.GetDbConnection().CreateCommand()) 
     { 
      command.CommandText = "SELECT ... WHERE ...> @p1)"; 
      command.CommandType = CommandType.Text; 
      var parameter = new SqlParameter("@p1",...); 

      this.DbContext.Database.OpenConnection(); 

      using (var result = command.ExecuteReader()) 
      { 
       while (result.Read()) 
       { 
        .... // Map to your entity 
       } 
      } 
     } 

हैं EFCore से नया है:

using Microsoft.EntityFrameworkCore.Infrastructure; 
using Microsoft.EntityFrameworkCore.Internal; 
using Microsoft.EntityFrameworkCore.Storage; 
using System.Threading; 
using System.Threading.Tasks; 

namespace Microsoft.EntityFrameworkCore 
{ 
    public static class RDFacadeExtensions 
    { 
     public static RelationalDataReader ExecuteSqlQuery(this DatabaseFacade databaseFacade, string sql, params object[] parameters) 
     { 
      var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>(); 

      using (concurrencyDetector.EnterCriticalSection()) 
      { 
       var rawSqlCommand = databaseFacade 
        .GetService<IRawSqlCommandBuilder>() 
        .Build(sql, parameters); 

       return rawSqlCommand 
        .RelationalCommand 
        .ExecuteReader(
         databaseFacade.GetService<IRelationalConnection>(), 
         parameterValues: rawSqlCommand.ParameterValues); 
      } 
     } 

     public static async Task<RelationalDataReader> ExecuteSqlQueryAsync(this DatabaseFacade databaseFacade, 
                  string sql, 
                  CancellationToken cancellationToken = default(CancellationToken), 
                  params object[] parameters) 
     { 

      var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>(); 

      using (concurrencyDetector.EnterCriticalSection()) 
      { 
       var rawSqlCommand = databaseFacade 
        .GetService<IRawSqlCommandBuilder>() 
        .Build(sql, parameters); 

       return await rawSqlCommand 
        .RelationalCommand 
        .ExecuteReaderAsync(
         databaseFacade.GetService<IRelationalConnection>(), 
         parameterValues: rawSqlCommand.ParameterValues, 
         cancellationToken: cancellationToken); 
      } 
     } 
    } 
} 

इसका इस्तेमाल करने के लिए का एक उदाहरण है एसक्यूएल इंजेक्शन से बचने के लिए एसक्लपैमरेटर को आज़माएं।

 dbData.Product.FromSql("SQL SCRIPT"); 

FromSql पूर्ण क्वेरी के साथ काम नहीं करता है। उदाहरण यदि आप एक WHERE खंड शामिल करना चाहते हैं तो इसे अनदेखा कर दिया जाएगा।

कुछ लिंक:

Executing Raw SQL Queries using Entity Framework Core

Raw SQL Queries

3

बिल्डिंग अन्य उत्तर मैं इस सहायक उस कार्य को पूरा करता है लिखा है, उदाहरण के उपयोग सहित पर:

public static class Helper 
{ 
    public static List<T> RawSqlQuery<T>(string query, Func<DbDataReader, T> map) 
    { 
     using (var context = new WannaSportContext()) 
     { 
      using (var command = context.Database.GetDbConnection().CreateCommand()) 
      { 
       command.CommandText = query; 
       command.CommandType = CommandType.Text; 

       context.Database.OpenConnection(); 

       using (var result = command.ExecuteReader()) 
       { 
        var entities = new List<T>(); 

        while (result.Read()) 
        { 
         entities.Add(map(result)); 
        } 

        return entities; 
       } 
      } 
     } 
    } 

उपयोग:

public class TopUser 
{ 
    public string Name { get; set; } 

    public int Count { get; set; } 
} 

var result = Helper.RawSqlQuery(
    "SELECT TOP 10 Name, COUNT(*) FROM Users U" 
    + " INNER JOIN Signups S ON U.UserId = S.UserId" 
    + " GROUP BY U.Name ORDER BY COUNT(*) DESC", 
    x => new TopUser { Name = (string)x[0], Count = (int)x[1] }); 

result.ForEach(x => Console.WriteLine($"{x.Name,-25}{x.Count}")); 

जैसे ही अंतर्निहित समर्थन जोड़ा जाता है, मैं इससे छुटकारा पाने की योजना बना रहा हूं। ईएफ कोर टीम के आर्थर विकर्स द्वारा statement के अनुसार यह पोस्ट 2.0 के लिए एक उच्च प्राथमिकता है। इस मुद्दे को here ट्रैक किया जा रहा है।

संबंधित मुद्दे