ডিবিসেট ছাড়াই কাঁচা এসকিউএল ক্যোয়ারী - সত্তা ফ্রেমওয়ার্ক কোর


121

সত্তা ফ্রেমওয়ার্ক কোর অপসারণের সাথে dbData.Database.SqlQuery<SomeModel>আমি আমার পূর্ণ-পাঠ্য অনুসন্ধানের অনুসন্ধানের জন্য একটি কাঁচা এসকিউএল কোয়েরি তৈরির কোনও সমাধান খুঁজে পাচ্ছি না যা টেবিলগুলির ডেটা এবং র‌্যাঙ্কটি ফিরিয়ে দেবে।

সত্তা ফ্রেমওয়ার্ক কোরে আমি কাঁচা এসকিউএল কোয়েরি তৈরি করতে দেখেছি কেবল সেই পদ্ধতিটিই dbData.Product.FromSql("SQL SCRIPT");কার্যকর নয় কারণ আমার কাছে কোনও ডিবিসেট নেই যা ক্যোয়ারীতে ফিরে আসা র‌্যাঙ্কটি ম্যাপ করবে।

কোন ধারনা???


15
আমি স্ক্যালকুইয়ারি <T> কে খুব মিস করব এবং আমার ডিবিকন্টেক্সটে কাস্টম ক্লাস মানচিত্র করতে চাই না যখন একটি নির্দিষ্ট ব্যবহারের ক্ষেত্রে সত্যই আমার সহজ ডিটিও প্রয়োজন। EF কোরটিতে
ম্যাট স্যান্ডার্স

4
Github.com/aspnet/EntityFramework/issues/1862 অনুসারে , এটি এখন EF কোর 1.2 এবং / অথবা 1.1.0-পূর্বরূপ1
ড্যান ফিল্ড

4
@ ডিভন কী বলেছে তার ভিত্তিতে, আমি এখন মাইক্রোসফ্টের এক্সটেনশন পদ্ধতিগুলি বুঝতে পেরে অনেক দীর্ঘ সময় কাটিয়েছি .এনটিটি ফ্রেমওয়ার্ককোর.সক্ল্যাওয়ার সার্ভার। এই এক্সটেনশন পদ্ধতিগুলি পাওয়ার আগে আপনাকে এটি আপনার প্রকল্পে যুক্ত করতে হবে।
ড্যানিয়েল

4
দীর্ঘস্থায়ীভাবে এটি একরকম আর্কিটেকচার নভোচারী সিদ্ধান্তের মতো বলে মনে হচ্ছে: "জনগণকে এটি চাওয়ার দরকার নেই"। আমার ধারণা আমি এই মামলার জন্য আমাকে ড্যাপার ইনস্টল করতে হবে। বিরক্তিকর।
ডার্ক বোয়ার

4
@ ম্যাটস্যান্ডার্স - এর মধ্যে আপনার ইউজারভয়েস লিঙ্কটি মারা গেছে বলে মনে হচ্ছে। কোথায় গেছে জানো?
ডার্ক বোয়ার

উত্তর:


139

আপনি EF কোর 2.1 বা EF কোর 3 এবং উচ্চতর সংস্করণ ব্যবহার করছেন তা নির্ভর করে ।

আপনি যদি EF কোর 2.1 ব্যবহার করছেন

আপনি যদি F মে 2018 সাল থেকে উপলব্ধ ইএফ কোর 2.1 প্রকাশের প্রার্থী 1 ব্যবহার করছেন তবে আপনি প্রস্তাবিত নতুন বৈশিষ্ট্যটি যা ক্যোয়ারী টাইপ এর সুবিধা নিতে পারেন।

কি ক্যোয়ারী টাইপ ?

সত্তা প্রকারের পাশাপাশি, একটি EF কোর মডেলটিতে ক্যোয়ারির ধরণ থাকতে পারে, যা সত্তার প্রকারের সাথে ম্যাপ না করা ডেটার বিরুদ্ধে ডেটাবেস কোয়েরি চালাতে ব্যবহার করা যেতে পারে।

কোয়েরি টাইপ কখন ব্যবহার করবেন?

অ্যাডহক থেকে এসএসএল () কোয়েরিগুলির জন্য রিটার্ন টাইপ হিসাবে পরিবেশন করা।

ডাটাবেস দর্শনে ম্যাপিং।

প্রাথমিক কী সংজ্ঞায়িত না করা সারণিতে ম্যাপিং Ma

মডেলটিতে সংজ্ঞায়িত প্রশ্নের ম্যাপিং।

সুতরাং আপনাকে আর আপনার প্রশ্নের উত্তর হিসাবে প্রস্তাবিত হ্যাকগুলি বা ওয়ার্কআরউন্ডগুলি আর করতে হবে না। কেবল এই পদক্ষেপগুলি অনুসরণ করুন:

প্রথমে আপনি টাইপের একটি নতুন সম্পত্তি নির্ধারণ করেছেন DbQuery<T>যেখানে Tশ্রেণীর ধরণটি আপনার এসকিউএল কোয়েরির কলাম মান বহন করবে। সুতরাং আপনার এই DbContextআপনার হবে:

public DbQuery<SomeModel> SomeModels { get; set; }

দ্বিতীয়ত FromSqlআপনার মতো পদ্ধতি ব্যবহার করুন DbSet<T>:

var result = context.SomeModels.FromSql("SQL_SCRIPT").ToList();
var result = await context.SomeModels.FromSql("SQL_SCRIPT").ToListAsync();

এছাড়াও লক্ষ করুন যে DdContextগুলি আংশিক শ্রেণি , তাই আপনি আপনার 'কাঁচা এসকিউএল ডিবিকিউয়ারি' সংজ্ঞাটি আপনার সেরা অনুসারে সংগঠিত করতে এক বা একাধিক পৃথক ফাইল তৈরি করতে পারেন।


আপনি যদি EF কোর 3.0 এবং উচ্চতর সংস্করণ ব্যবহার করছেন

ক্যোয়ারির ধরণটি এখন কীলেস সত্তার প্রকার হিসাবে পরিচিত । যেমনটি বলা হয়েছে উপরের ক্যোয়ারী প্রকারগুলি EF কোর 2.1 তে প্রবর্তিত হয়েছিল। আপনি যদি EF কোর 3.0 বা উচ্চতর সংস্করণ ব্যবহার করছেন তবে আপনার এখন কীবিহীন ট্র্যান্টিটি প্রকারগুলি ব্যবহার করে কনডাইডার করা উচিত কারণ ক্যোয়ারির ধরণগুলি এখন অপ্রচলিত হিসাবে চিহ্নিত।

এই বৈশিষ্ট্যটি কোয়েরি ধরণের নামে EF কোর ২.১ এ যুক্ত করা হয়েছে। EF কোর 3.0 এ ধারণাটি চাবিবিহীন সত্তার ধরণের নামকরণ করা হয়েছিল। [কীলেস] ডেটা টীকাগুলি ইএফসিওর 5.0 এ উপলব্ধ হয়ে উঠেছে।

চাবিহীন সত্তার প্রকারটি কখন ব্যবহার করতে হবে তার জন্য ক্যোয়ারির ধরণের মতো আমাদের কাছে এখনও একই পরিস্থিতিতে রয়েছে।

সুতরাং এটি ব্যবহার করার জন্য আপনাকে প্রথমে নীচের মতো পদ্ধতি কল SomeModelসহ [Keyless]ডেটা টিকা দিয়ে বা সাবলীল কনফিগারেশনের মাধ্যমে আপনার শ্রেণিকে চিহ্নিত করতে হবে .HasNoKey():

public DbSet<SomeModel> SomeModels { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SomeModel>().HasNoKey();
}

সেই কনফিগারেশনের পরে, আপনি আপনার এসকিউএল কোয়েরি চালানোর জন্য এখানে বর্ণিত একটি পদ্ধতি ব্যবহার করতে পারেন । উদাহরণস্বরূপ আপনি এটি ব্যবহার করতে পারেন:

var result = context.SomeModels.FromSqlRaw("SQL SCRIPT").ToList();

18
EF কোর ২.১ এবং তার বেশি ব্যবহার করার সময় এই উত্তরটি সেরা সমাধান হওয়া উচিত। 👍
হুয়াং

4
@ কোডনটফাউন্ড যদি আমার ফলাফলের প্রয়োজন না হয় বা এটি কোনও আদিম ধরণের (উদাহরণস্বরূপ bit)?
শিমি ওয়েটজ্যান্ডলার

6
কোডফার্স ব্যবহার করে এটি স্বয়ংক্রিয়ভাবে এই সমস্ত বৈশিষ্ট্য সহ একটি টেবিল তৈরি [NotMapped]করেছে, SomeModelsক্লাসে যুক্ত করা আমার পক্ষে কাজ করে না। আমি কিছু মিস করেছি?
জিন-পল

7
EF কোর 3.0 DbQueryকেবল চাবিবিহীন সত্তা প্রকারেরDbSet সাথে ব্যবহার করার পক্ষে অবহেলা করে ।
নেটমেজ

7
শুধু এফওয়াইআই, ইএফ কোর 3.0 এ কিছু ত্রুটির কারণে, একটি কোড-প্রথম স্থানান্তর এখনও হাসনোকি () দ্বারা চিহ্নিত চিহ্নিত সত্তাগুলিতে এমনকি একটি টেবিল তৈরি করার চেষ্টা করবে। সুতরাং আপনাকেও যোগ করতে হবে। টুভিউ (নাল)। উদাহরণস্বরূপ modelBuilder.Entity<MyData>().HasNoKey().ToView(null);@ জিন-পল আমি মনে করি এটি আপনার সমস্যার সমাধান করে
stann1

41

অন্যান্য উত্তরের উপর ভিত্তি করে আমি এই সহায়কটি লিখেছি যা উদাহরণটি ব্যবহার সহ কার্য সম্পাদন করে:

public static class Helper
{
    public static List<T> RawSqlQuery<T>(string query, Func<DbDataReader, T> map)
    {
        using (var context = new DbContext())
        {
            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}"));

বিল্ট-ইন সমর্থন যুক্ত হওয়ার সাথে সাথে এ থেকে মুক্তি পাওয়ার পরিকল্পনা করছি plan ইএফ কোর দলের পক্ষ থেকে আর্থার ভিকার্সের একটি বিবৃতি অনুসারে এটি ২.০ পোস্টের জন্য একটি উচ্চ অগ্রাধিকার। বিষয়টি এখানে ট্র্যাক করা হচ্ছে ।


সুন্দর উত্তর, ভাল লেগেছে।
সেবু

31

ইএফ কোরটিতে আপনি আর "ফ্রি" কাঁচা স্কিল চালাতে পারবেন না। আপনাকে একটি পোকো ক্লাস এবং DbSetসেই শ্রেণীর জন্য একটি নির্ধারণ করতে হবে । আপনার ক্ষেত্রে আপনাকে র‌্যাঙ্কটি নির্ধারণ করতে হবে :

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

এটি অবশ্যই পঠনযোগ্য হবে .AsNoTracking()কলটি অন্তর্ভুক্ত করা কার্যকর হবে ।

সম্পাদনা - EF কোর 3.0 এ ব্রেকিং পরিবর্তন:

DbQuery () এখন অপ্রচলিত, পরিবর্তে DbSet () ব্যবহার করা উচিত (আবার)। আপনার যদি কীবিহীন সত্ত্বা থাকে, যেমন এটির জন্য প্রাথমিক কী প্রয়োজন হয় না, আপনি হাসনকি () পদ্ধতিটি ব্যবহার করতে পারেন :

ModelBuilder.Entity<SomeModel>().HasNoKey()

আরও তথ্য এখানে পাওয়া যাবে


4
সুতরাং আমার ধারণা আমি DbContextএকটি নতুন সম্পত্তি অন্তর্ভুক্ত করতে প্রসারিত করতে হবে DbSet<Rank> Rank { get; set; }। লিনকের রেফারেন্সে এখন এর কী কী প্রভাব পড়বে? অর্থাৎ আমরা এখন DBContext.Rank.Where(i => i.key == 1)এই জাতীয় বিবৃতি ব্যবহার করতে সক্ষম হব এবং এসকিউএল-তে এই বিবৃতিটির কোনও প্রয়োগ নেই এবং তাই ব্যর্থ হবে?
ডেভিড হারলো

এই সেটটির বিপরীতে নির্গত লিঙ্ককে স্মরণে সমাধান করতে হবে। যদি আপনাকে আলাদা WHERE বর্গক্ষেত্রের অনুচ্ছেদ নির্গত করতে হয় তবে আপনাকে সেগুলি প্যারামিটার হিসাবে অন্তর্ভুক্ত করতে হবে বা আলাদা স্ক্রিপ্ট তৈরি করতে হবে।
ই-ব্যাট

আমার ডিবিসেটে "ফরাসস্কুল" পদ্ধতি নেই। এটি কি একটি এক্সটেনশন আমি মিস করছি?
বারুইন

4
@ বীরউইন, আপনাকে নামস্থান মাইক্রোসফ্ট আমদানি করতে হবে ntএন্টি ফ্রেমওয়ার্ককোর
ই-ব্যাট

21

আপনি ইএফ কোরে কাঁচা এসকিএল চালাতে পারেন - এই প্রকল্পটি আপনার প্রকল্পে যুক্ত করুন। এটি আপনাকে কাঁচা এসকিউএল সম্পাদন করতে এবং কোনও পোকো এবং ডিবিসেটকে সংজ্ঞায়িত না করে কাঁচা ফলাফল পেতে দেয়। আসল উদাহরণের জন্য https://github.com/aspnet/EntityFramework/issues/1862#issuecomment-220787464 দেখুন ।

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

এটি কীভাবে ব্যবহার করা যায় তার একটি উদাহরণ এখানে:

// 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]);
    }
}

19

আপাতত, ইএফসিওর থেকে নতুন কিছু না আসা পর্যন্ত আমি একটি কমান্ড ব্যবহার করে ম্যানুয়ালি ম্যাপ করব

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

      this.DbContext.Database.OpenConnection();

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

এসকিএল ইনজেকশন এড়াতে স্কেলপ্যারামিটার চেষ্টা করুন।

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

FromSql সম্পূর্ণ প্রশ্নের সাথে কাজ করে না। উদাহরণস্বরূপ আপনি যদি একটি WHERE ধারা যুক্ত করতে চান তবে তা উপেক্ষা করা হবে।

কিছু লিঙ্ক:

সত্তা ফ্রেমওয়ার্ক কোর ব্যবহার করে কাঁচা এসকিউএল কোয়েরিগুলি কার্যকর করা

কাঁচা এসকিউএল অনুসন্ধান


8

আপনি এটি ব্যবহার করতে পারেন ( https://github.com/aspnet/EntityFrameworkCore/issues/1862#issuecomment-451671168 থেকে ):

public static class SqlQueryExtensions
{
    public static IList<T> SqlQuery<T>(this DbContext db, string sql, params object[] parameters) where T : class
    {
        using (var db2 = new ContextForQueryType<T>(db.Database.GetDbConnection()))
        {
            return db2.Query<T>().FromSql(sql, parameters).ToList();
        }
    }

    private class ContextForQueryType<T> : DbContext where T : class
    {
        private readonly DbConnection connection;

        public ContextForQueryType(DbConnection connection)
        {
            this.connection = connection;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // switch on the connection type name to enable support multiple providers
            // var name = con.GetType().Name;
            optionsBuilder.UseSqlServer(connection, options => options.EnableRetryOnFailure());

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<T>().HasNoKey();
            base.OnModelCreating(modelBuilder);
        }
    }
}

এবং ব্যবহার:

    using (var db = new Db())
    {
        var results = db.SqlQuery<ArbitraryType>("select 1 id, 'joe' name");
        //or with an anonymous type like this
        var results2 = db.SqlQuery(() => new { id =1, name=""},"select 1 id, 'joe' name");
    }

modelBulider.Query<T>()EntityFramework কোর 3 অবচিত
জাফর

EF কোর 3+ এর জন্য আপডেট হয়েছে
এরিকিজ

7

কোর ২.১ এ আপনি এরকম কিছু করতে পারেন:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
       modelBuilder.Query<Ranks>();
}

এবং তারপরে আপনাকে এসকিউএল প্রক্রিয়াটি সংজ্ঞায়িত করুন, যেমন:

public async Task<List<Ranks>> GetRanks(string value1, Nullable<decimal> value2)
{
    SqlParameter value1Input = new SqlParameter("@Param1", value1?? (object)DBNull.Value);
    SqlParameter value2Input = new SqlParameter("@Param2", value2?? (object)DBNull.Value);

    List<Ranks> getRanks = await this.Query<Ranks>().FromSql("STORED_PROCEDURE @Param1, @Param2", value1Input, value2Input).ToListAsync();

    return getRanks;
}

এইভাবে র‌্যাঙ্কস মডেলটি আপনার ডিবিতে তৈরি হবে না।

এখন আপনার নিয়ামক / ক্রিয়ায় আপনি কল করতে পারেন:

List<Ranks> gettingRanks = _DbContext.GetRanks(value1,value2).Result.ToListAsync();

এইভাবে আপনি কাঁচা এসকিউএল পদ্ধতিগুলি কল করতে পারেন।


FromSqlপ্যারাম কেবল তৈরি ছাড়া পাস করা যেতে পারে SqlParameterবস্তু: FromSql($"STORED_PROCEDURE {value1}, {value2}")বা FromSql("STORED_PROCEDURE {0}, {1}", value1, value2)(তারা পালিয়ে হবে)।
মাজিদ

7

নিউজ প্যাকেজ যুক্ত করুন - মাইক্রোসফ্ট.এন্টি ফ্রেমওয়ার্ককোর. সম্পর্কিত

using Microsoft.EntityFrameworkCore;
...
await YourContext.Database.ExecuteSqlCommandAsync("... @p0, @p1", param1, param2 ..)

এটি একটি int হিসাবে সারি সংখ্যা ফেরত দেবে

দেখুন - https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatediafacadeextensions.executesqlcommand?view=efcore-3.0


4
: দয়া করে নোট এই শুধুমাত্র কমান্ড দ্বারা প্রভাবিত সারির সংখ্যা আসতে করবে stackoverflow.com/a/49861799/299756
kalyfe

ঠিক আমার যা প্রয়োজন আমি মাইক্রোসফ্ট.এনটিটি ফ্রেমওয়ার্ককোর ৩.১.১ ব্যবহার করছি এবং আরএডাব্লু কোয়েরি এবং এসপি কার্যকর করার কোনও উপায় নেই। এর জন্য আপনাকে অনেক ধন্যবাদ!
জয়সোনগ্রাস

5

এটি ব্যবহার করে দেখুন: (এক্সটেনশন পদ্ধতি তৈরি করুন)

public static List<T> ExecuteQuery<T>(this dbContext db, string query) where T : class, new()
        {
            using (var command = db.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = query;
                command.CommandType = CommandType.Text;

                db.Database.OpenConnection();

                using (var reader = command.ExecuteReader())
                {
                    var lst = new List<T>();
                    var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
                    while (reader.Read())
                    {
                        var newObject = new T();
                        for (var i = 0; i < reader.FieldCount; i++)
                        {
                            var name = reader.GetName(i);
                            PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
                            if (prop == null)
                            {
                                continue;
                            }
                            var val = reader.IsDBNull(i) ? null : reader[i];
                            prop.SetValue(newObject, val, null);
                        }
                        lst.Add(newObject);
                    }

                    return lst;
                }
            }
        }

ব্যবহার:

var db = new dbContext();
string query = @"select ID , Name from People where ... ";
var lst = db.ExecuteQuery<PeopleView>(query);

আমার মডেল: (নেই DbSet):

public class PeopleView
{
    public int ID { get; set; }
    public string Name { get; set; }
}

পরীক্ষিত .netCore 2.2 and 3.0

দ্রষ্টব্য: এই সমাধানটির ধীর পারফরম্যান্স রয়েছে


কেবলমাত্র প্রথম রেকর্ডের জন্য একবারে নামে সম্পত্তি অনুসন্ধান করুন এবং পরবর্তী রেকর্ডগুলিতে ব্যবহারের জন্য কলাম সূচী দ্বারা প্রপার্টিআইএনফো [] প্রচ্ছদ তৈরি করুন।
পেটর ভোবর্নেক

@AminRostami দারুন কাজ
sebu

2

সরাসরি ওপির দৃশ্যের লক্ষ্যবস্তু নয়, তবে যেহেতু আমি এ নিয়ে লড়াই করে যাচ্ছি, তাই আমি এই প্রাক্তনগুলিকে বাদ দিতে চাই। এমন পদ্ধতি যা এর মাধ্যমে কাঁচা এসকিউএল কার্যকর করা সহজ করে তোলে DbContext:

public static class DbContextCommandExtensions
{
  public static async Task<int> ExecuteNonQueryAsync(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return await command.ExecuteNonQueryAsync();
    }
  }

  public static async Task<T> ExecuteScalarAsync<T>(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return (T)await command.ExecuteScalarAsync();
    }
  }
}

1

সত্তা ফ্রেমওয়ার্ক কোরের এই সীমাবদ্ধতাটি বাইপাস করতে আমি ড্যাপারটি ব্যবহার করেছি ।

IDbConnection.Query

হয় স্কয়ার কোয়েরি বা একাধিক পরামিতি সহ সঞ্চিত পদ্ধতিতে কাজ করছে। উপায় দ্বারা এটি কিছুটা দ্রুত ( মানদণ্ড পরীক্ষা দেখুন )

Dapper শিখতে সহজ। প্যারামিটার সহ সঞ্চিত প্রক্রিয়াটি লিখতে এবং চালাতে 15 মিনিট সময় লেগেছে। যাইহোক আপনি EF এবং ড্যাপার উভয়ই ব্যবহার করতে পারেন। নীচে একটি উদাহরণ দেওয়া হল:

 public class PodborsByParametersService
{
    string _connectionString = null;


    public PodborsByParametersService(string connStr)
    {
        this._connectionString = connStr;

    }

    public IList<TyreSearchResult> GetTyres(TyresPodborView pb,bool isPartner,string partnerId ,int pointId)
    {

        string sqltext  "spGetTyresPartnerToClient";

        var p = new DynamicParameters();
        p.Add("@PartnerID", partnerId);
        p.Add("@PartnerPointID", pointId);

        using (IDbConnection db = new SqlConnection(_connectionString))
        {
            return db.Query<TyreSearchResult>(sqltext, p,null,true,null,CommandType.StoredProcedure).ToList();
        }


        }
}

0

আপনি কোয়েরি ফার্স্টও ব্যবহার করতে পারেন । ড্যাপারের মতো এটিও পুরোপুরি EF এর বাইরে। ড্যাপার (বা ইএফ) এর বিপরীতে, আপনার পোকো বজায় রাখার দরকার নেই, আপনি আপনার এসকিউএল এসকিউএলকে একটি সত্য পরিবেশে সম্পাদনা করুন এবং এটি ডিবি-র বিরুদ্ধে ক্রমাগত পুনর্বিবেচিত হয়। দাবি অস্বীকার: আমি কোয়েরি ফার্স্টের লেখক।


0

আমার কেস কাঁচা এসকিউএল এর পরিবর্তে সঞ্চিত পদ্ধতি ব্যবহার করে

একটি ক্লাস তৈরি

Public class School
{
    [Key]
    public Guid SchoolId { get; set; }
    public string Name { get; set; }
    public string Branch { get; set; }
    public int NumberOfStudents  { get; set; }
}

আমার DbContextক্লাসে নীচে যুক্ত হয়েছে

public DbSet<School> SP_Schools { get; set; }

সঞ্চিত পদ্ধতিটি কার্যকর করতে:

var MySchools = _db.SP_Schools.FromSqlRaw("GetSchools @schoolId, @page, @size ",
              new SqlParameter("schoolId", schoolId),
              new SqlParameter("page", page),
              new SqlParameter("size", size)))
.IgnoreQueryFilters();

0

আমি জানি এটি একটি পুরানো প্রশ্ন তবে সম্ভবত এটি কাউকে ডিটিএসকে ডিবিএস হিসাবে যুক্ত না করে স্টোরেজ পদ্ধতিগুলি কল করতে সহায়তা করে।

https://stackoverflow.com/a/62058345/3300944


0

এই সমাধানটি @ পিয়াস থেকে সমাধানের উপর প্রচুর ঝোঁক। এসকিউএল ইনজেকশন প্রশমিত করতে আমি ক্যোয়ারী প্যারামিটারগুলি সমর্থন করার বিকল্পটি যুক্ত করতে চেয়েছিলাম এবং এটিকে আরও কিছুটা সংহত করার জন্য আমি এটিটি ফ্রেমওয়ার্ক কোরের জন্য DbContext ডেটাবেসফ্যাকডকে এটিকে একটি এক্সটেনশানও বন্ধ করে দিতে চেয়েছিলাম।

প্রথমে এক্সটেনশন সহ একটি নতুন শ্রেণি তৈরি করুন:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;

namespace EF.Extend
{

    public static class ExecuteSqlExt
    {
        /// <summary>
        /// Execute raw SQL query with query parameters
        /// </summary>
        /// <typeparam name="T">the return type</typeparam>
        /// <param name="db">the database context database, usually _context.Database</param>
        /// <param name="query">the query string</param>
        /// <param name="map">the map to map the result to the object of type T</param>
        /// <param name="queryParameters">the collection of query parameters, if any</param>
        /// <returns></returns>
        public static List<T> ExecuteSqlRawExt<T, P>(this DatabaseFacade db, string query, Func<DbDataReader, T> map, IEnumerable<P> queryParameters = null)
        {
            using (var command = db.GetDbConnection().CreateCommand())
            {
                if((queryParameters?.Any() ?? false))
                    command.Parameters.AddRange(queryParameters.ToArray());

                command.CommandText = query;
                command.CommandType = CommandType.Text;

                db.OpenConnection();

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

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

                    return entities;
                }
            }
                
        }
    }

}

উপরের দিকে নোট করুন যে "টি" হ'ল রিটার্নের ধরণ এবং "পি" আপনার ক্যোয়ারী প্যারামিটারগুলির প্রকার যা আপনি মাইএসকিএল, এসকিএল, ইত্যাদি ব্যবহার করছেন যদি তার ভিত্তিতে পরিবর্তিত হয়।

পরবর্তী আমরা একটি উদাহরণ দেখাব। আমি মাইএসকিএল ইএফ কোর সক্ষমতাটি ব্যবহার করছি, তাই আমরা আরও নির্দিষ্ট মাইএসকিএল বাস্তবায়নের সাথে কীভাবে উপরের জেনেরিক এক্সটেনশনটি ব্যবহার করতে পারি তা আমরা দেখতে পাব:

//add your using statement for the extension at the top of your Controller
//with all your other using statements
using EF.Extend;

//then your your Controller looks something like this
namespace Car.Api.Controllers
{

    //Define a quick Car class for the custom return type
    //you would want to put this in it's own class file probably
    public class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public string DisplayTitle { get; set; }
    }

    [ApiController]
    public class CarController : ControllerBase
    {
        private readonly ILogger<CarController> _logger;
        //this would be your Entity Framework Core context
        private readonly CarContext _context;

        public CarController(ILogger<CarController> logger, CarContext context)
        {
            _logger = logger;
            _context = context;
        }

        //... more stuff here ...

       /// <summary>
       /// Get car example
       /// </summary>
       [HttpGet]
       public IEnumerable<Car> Get()
       {
           //instantiate three query parameters to pass with the query
           //note the MySqlParameter type is because I'm using MySql
           MySqlParameter p1 = new MySqlParameter
           {
               ParameterName = "id1",
               Value = "25"
           };

           MySqlParameter p2 = new MySqlParameter
           {
               ParameterName = "id2",
               Value = "26"
           };

           MySqlParameter p3 = new MySqlParameter
           {
               ParameterName = "id3",
               Value = "27"
           };

           //add the 3 query parameters to an IEnumerable compatible list object
           List<MySqlParameter> queryParameters = new List<MySqlParameter>() { p1, p2, p3 };

           //note the extension is now easily accessed off the _context.Database object
           //also note for ExecuteSqlRawExt<Car, MySqlParameter>
           //Car is my return type "T"
           //MySqlParameter is the specific DbParameter type MySqlParameter type "P"
           List<Car> result = _context.Database.ExecuteSqlRawExt<Car, MySqlParameter>(
        "SELECT Car.Make, Car.Model, CONCAT_WS('', Car.Make, ' ', Car.Model) As DisplayTitle FROM Car WHERE Car.Id IN(@id1, @id2, @id3)",
        x => new Car { Make = (string)x[0], Model = (string)x[1], DisplayTitle = (string)x[2] }, 
        queryParameters);

           return result;
       }
    }
}

ক্যোয়ারিতে সারিগুলি ফিরে আসবে যেমন:
"ফোর্ড", "এক্সপ্লোরার", "ফোর্ড এক্সপ্লোরার"
"টেসলা", "মডেল এক্স", "টেসলা মডেল এক্স"

প্রদর্শনের শিরোনামটি একটি ডাটাবেস কলাম হিসাবে সংজ্ঞায়িত করা হয়নি, সুতরাং এটি ডিফল্টরূপে EF কার মডেলের অংশ হবে না। আমি সম্ভাব্য সমাধানগুলির মধ্যে একটি হিসাবে এই পদ্ধতির পছন্দ করি। এই পৃষ্ঠার অন্যান্য উত্তরগুলি [নটম্যাপড] ডিকোরিটারের সাথে এই সমস্যাটির সমাধান করার অন্যান্য উপায়গুলি উল্লেখ করে, যা আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে আরও উপযুক্ত পদ্ধতির হতে পারে।

নোট করুন যে এই উদাহরণের কোডটি স্পষ্টতই এটির প্রয়োজনের চেয়ে বেশি ভার্বোজ, তবে আমি ভেবেছিলাম এটি উদাহরণটি আরও পরিষ্কার করে দিয়েছে।


0

আসলে আপনি একটি জেনেরিক সংগ্রহশালা তৈরি করতে পারেন এবং এর মতো কিছু করতে পারেন

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : BaseEntity
{
    private readonly DataContext context;
    private readonly DbSet<TEntity> dbSet;

    public GenericRepository(DataContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

   
    public IEnumerable<TEntity> ExecuteCommandQuery(string command)
        => dbSet.FromSqlRaw(command);

}

সংযোজন: মাইক্রোসফ্ট.এনটিটি ফ্রেমওয়ার্ককোয়ার থেকে ফোরস্কুলআরও নেই। মাইক্রোসফ্ট ইনস্টল করার জন্য এটি নেসেসারি Eএনটিটি ফ্রেমওয়ার্ককোর thisএই পদ্ধতিটি ব্যবহারের জন্য সম্পর্কিত।
কেট

-7

সত্তা ফ্রেমওয়ার্ক 6 এর সাহায্যে আপনি নীচের মতো কিছু কার্যকর করতে পারেন

হিসাবে মডেল ক্লাস তৈরি করুন

Public class User
{
        public int Id { get; set; }
        public string fname { get; set; }
        public string lname { get; set; }
        public string username { get; set; }
}

নিচের মতো কাঁচা ডিকিউএল এসকিউএল কমান্ড কার্যকর করুন:

var userList = datacontext.Database.SqlQuery<User>(@"SELECT u.Id ,fname , lname ,username FROM dbo.Users").ToList<User>();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.