লিনকুতে অপারেটর পছন্দ করুন


89

এসকিউএল LIKEঅপারেটরের অনুরূপ সি # লিনকিউ এক্সপ্রেশনটিতে স্ট্রিংগুলির তুলনা করার কোনও উপায় আছে কি ?

ধরুন আমার কাছে স্ট্রিং লিস্ট আছে। এই তালিকায় আমি একটি স্ট্রিং অনুসন্ধান করতে চাই। এসকিউএল-তে আমি লিখতে পারি:

SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%'

উপরের পরিবর্তে, ক্যোয়ারী একটি লিনাক সিনট্যাক্স চায়।

using System.Text.RegularExpressions;
…

var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase);
var sPortCode = Database.DischargePorts
                .Where(p => regex.IsMatch(p.PortName))
                .Single().PortCode;

আমার উপরের লিনকিউ সিনট্যাক্সটি কাজ করে না। আমার কী ভুল হয়েছে?


4
আপনি যখন এটি স্থাপন করেছিলেন তখন এই ক্যোয়ারীটি মূলত আমার পক্ষে কাজ করেছিল। তবে, আমি মঙ্গোডিবি লিনক ড্রাইভারটি ব্যবহার করছি এবং প্রতিটি লিনক সরবরাহকারীর মধ্যে প্রয়োগের পার্থক্য রয়েছে ... যাইহোক, ধন্যবাদ।
মার্ক এওয়ার

এটি লিনকিউ-তে পছন্দ করার মতো সেরা সমাধান আমি খুঁজে পেয়েছি। ধন্যবাদ - @ প্রণয়-রানা
অভিষেক তোমার

আপনি কী চান এবং "কাজ করে না" কী তা সত্য তা পরিষ্কার নয়। আপনি কি একটি লিনকু-টু-অবজেক্টের সমতুল্য Like, বা এমন কোনও ফাংশন চান যা Likeআপনি যে ওআরএম ব্যবহার করছেন তাতে অনুবাদ করে? পরে যদি, কোন ওআরএম? এছাড়াও, দয়া করে উত্তরগুলির মধ্যে একটি গ্রহণ করুন যদি এটি আপনাকে সহায়তা করে। আপনি যা জিজ্ঞাসা করছেন তার একটি অস্পষ্ট ধারণা ব্যতীত লোকেরা কিছুই উত্তরের ভিত্তিতে জড়িত রাখে।
গার্ট আর্নল্ড

উত্তর:


143

সাধারণত আপনি String.StartsWith/ EndsWith/ ব্যবহার করেন Contains। উদাহরণ স্বরূপ:

var portCode = Database.DischargePorts
                       .Where(p => p.PortName.Contains("BALTIMORE"))
                       .Single()
                       .PortCode;

আমি জানি না যদিও লিনকিউ এর মাধ্যমে এসকিউএল এর মাধ্যমে নিয়মিত নিয়মিত প্রকাশ করার কোনও উপায় আছে কিনা। (মনে রাখবেন যে আপনি যে সরবরাহকারীর ব্যবহার করছেন তার উপর এটি নির্ভর করে - এটি লিনকিউতে অবজেক্টে ভাল হবে; সরবরাহকারী কলটিকে তার স্থানীয় কোয়েরি ফর্ম্যাটে যেমন, এসকিউএল রূপান্তর করতে পারে কিনা তা বিষয়))

সম্পাদনা: বিটকফু যেমন বলেছে, Singleআপনি যখন ঠিক একটি ফলাফল আশা করেন তখন ব্যবহার করা উচিত - যখন এটির ক্ষেত্রে সমস্যা না হয়। এর বিকল্প SingleOrDefault, FirstOrDefaultবা Firstতার উপর নির্ভর করে ব্যবহার করা উচিত ঠিক যা প্রত্যাশা করছে।


বন্ধু তবে, একটি সমস্যা আছে, আমার তালিকায় "বেল্টিমোর" রয়েছে এবং আমার প্রদত্ত তুলনা প্যারামিটারটি হল "বাল্টিমোর [এমডি], মার্কিন"।
শামীম

4
নীচে আমার বক্তব্যটি দেখুন, এটি একক () পদ্ধতি থেকে আসতে পারে। ফার্স্টআরডিফল্ট () ব্যবহার করা ভাল
বিটকেফু

4
@ শামীম: সুতরাং আপনার ডেটাতে আপনি যে স্ট্রিংটি খুঁজছেন তা ধারণ করে না? কীভাবে আপনি এটি এসকিউএল-তে কাজ করতে পারবেন?
জন স্কিটি

এসকিউএল এ আপনি কোনও ফলাফল সেট পাবেন না - সি # এ আপনি একটি ব্যতিক্রম পাবেন exception কোন ফলাফলের পরিবর্তে যা কিছুটা আলাদা। এজন্য আমি ফার্স্টআরডিফল্ট ব্যবহার করার পরামর্শ দিয়েছি।
BitKFu

@ বিটকফু শুরু থেকে Single(), SingleOrDefault()আমার পরবর্তী পদক্ষেপ হবে, যদি না আমরা পুরো প্রসঙ্গটি বুঝতে পারি ...
মার্ক গ্র্যাভেল

34

রেজেক্স? না তবে সেই প্রশ্নের জন্য আপনি কেবল ব্যবহার করতে পারেন:

 string filter = "BALTIMORE";
 (blah) .Where(row => row.PortName.Contains(filter)) (blah)

আপনি যদি সত্যিই এসকিউএল চান LIKE, আপনি ব্যবহার করতে পারেন System.Data.Linq.SqlClient.SqlMethods.Like(...), যা LIKEএসকিউএল সার্ভারে লিনিক-টু-এসকিউএল মানচিত্র করে ।


@ ম্যাসলো - আমার দক্ষতার ক্ষেত্র নয়, আমি ভয় করি - তবে আমি বিশ্বাস করি না যে ম্যাপিংয়ের একটি দুর্দান্ত পরিষ্কার উপায় আছে যা সমস্ত EF বাস্তবায়নের ক্ষেত্রে, তাই ... না।
মার্ক গ্র্যাভেল

4
এটি এসকিউএল বাস্তবায়নে কাজ করতে পারে তবে একটি স্ট্যান্ডার্ড অবজেক্ট সংগ্রহের সাথে কাজ করে না
ক্রিস ম্যাকগ্রা

13

ভাল ... কখনও কখনও এটি ব্যবহার করতে অস্বস্তিকর হতে পারে Contains, StartsWithবা EndsWithবিশেষত যখন অনুসন্ধানের মান নির্ধারণ করে LIKEযেমন বিকাশকারী StartsWithফাংশনটি ব্যবহার করার জন্য বিকাশকারীর কাছ থেকে 'মান%' পাস করা হয় । সুতরাং আমি IQueryableঅবজেক্টের জন্য এক্সটেনশন লিখতে সিদ্ধান্ত নিয়েছি ।

ব্যবহার

// numbers: 11-000-00, 00-111-00, 00-000-11

var data1 = parts.Like(p => p.Number, "%11%");
// result: 11-000-00, 00-111-00, 00-000-11

var data2 = parts.Like(p => p.Number, "11%");
// result: 11-000-00

var data3 = parts.Like(p => p.Number, "%11");
// result: 00-000-11

কোড

public static class LinqEx
{
    private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
    private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });

    public static Expression<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value)
    {
        var param = Expression.Parameter(typeof(TSource), "t");
        var propertyInfo = GetPropertyInfo(property);
        var member = Expression.Property(param, propertyInfo.Name);

        var startWith = value.StartsWith("%");
        var endsWith = value.EndsWith("%");

        if (startWith)
            value = value.Remove(0, 1);

        if (endsWith)
            value = value.Remove(value.Length - 1, 1);

        var constant = Expression.Constant(value);
        Expression exp;

        if (endsWith && startWith)
        {
            exp = Expression.Call(member, ContainsMethod, constant);
        }
        else if (startWith) 
        {
            exp = Expression.Call(member, EndsWithMethod, constant);
        }
        else if (endsWith)
        {
            exp = Expression.Call(member, StartsWithMethod, constant);
        }
        else
        {
            exp = Expression.Equal(member, constant);
        }

        return Expression.Lambda<Func<TSource, bool>>(exp, param);
    }

    public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value)
    {
        return source.Where(LikeExpression(parameter, value));
    }

    private static PropertyInfo GetPropertyInfo(Expression expression)
    {
        var lambda = expression as LambdaExpression;
        if (lambda == null)
            throw new ArgumentNullException("expression");

        MemberExpression memberExpr = null;

        switch (lambda.Body.NodeType)
        {
            case ExpressionType.Convert:
                memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
                break;
            case ExpressionType.MemberAccess:
                memberExpr = lambda.Body as MemberExpression;
                break;
        }

        if (memberExpr == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");


        var output = memberExpr.Member as PropertyInfo;

        if (output == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");

        return output;
    }
}

আপনার সাথে এমন কোনও সংস্করণ রয়েছে যা কাজ করে IEnumerable?
নিক ম্যানারিন

9

নেটিভ লিনকুইতে আপনি Contains/StartsWith/EndsWithরেজিপ্যাক্সের সংমিশ্রণ ব্যবহার করতে পারেন ।

LINQ2SQL- এ ব্যবহার পদ্ধতি SqlMethods.Like()

    from i in db.myTable
    where SqlMethods.Like(i.field, "tra%ata")
    select i

এই বৈশিষ্ট্যটি ব্যবহার করতে એસেম্বলি: System.Data.Linq (System.Data.Linq.dll এ) যুক্ত করুন।


আমি বুঝতে পারি যে ওপি আসলে লিঙ্ক 2 এসকিউএল বলেনি, তবে এটি নিহিত বলে মনে হয়েছে। কারণ আমি এখানে যে StartsWith(), Contains()ইত্যাদি না না Linq2SQL (সঙ্গে কাজ অন্তত আমি পেতে "LINQ অভিব্যক্তি ... অনুবাদ করা যাবে না ..." এবং ব্যবহার ToList করার একটি নির্দেশ () "ক্লায়েন্ট মূল্যায়ন" জন্য -যেটা আমি ' আমি ইতিমধ্যে করছি Note দ্রষ্টব্য, EF কোর-এ এটি সরানো হয়েছেEF.Functions.Like()
অ্যাসপেক্স

8

জন স্কিটি এবং মার্ক গ্র্যাভেল ইতিমধ্যে উল্লিখিত হিসাবে, আপনি সহজভাবে একটি শর্ত থাকে take তবে আপনার মত ক্যোয়ারির ক্ষেত্রে, একটি একক () বিবৃতি নেওয়া খুব বিপজ্জনক, কারণ এর দ্বারা বোঝা যায় যে আপনি কেবল 1 টি ফলাফল পেয়েছেন। আরও ফলাফলের ক্ষেত্রে, আপনি একটি দুর্দান্ত ব্যতিক্রম পাবেন :)

সুতরাং আমি সিঙ্গল () এর পরিবর্তে ফার্স্টআরডিফল্ট () ব্যবহার করতে পছন্দ করব:

var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE"));
var portcode = first != null ? first.PortCode : string.Empty;

যদি এটি আমাদের দৃ expect় প্রত্যাশা হয় যে ঠিক একটি মিল আছে, তবে সিঙ্গেল "বিপজ্জনক" নয় - এটি "সঠিক"। এটা সব "অন্তত একটি", "সবচেয়ে এক", "ঠিক একটি", ইত্যাদি আমরা কোন ডেটা ... "কোন সংখ্যা" সম্পর্কে দাবি করছেন নিচে আসে,
মার্ক Gravell

4
প্রসঙ্গ উপর নির্ভর করে, এটা হতে পারে ... এটা ক্যোয়ারী প্রত্যাশা ওপর সম্পূর্ণভাবে নির্ভর করে
মার্ক Gravell

"ফাঁকা" বা "%" অনুসন্ধানের কী হবে? এটি কি "বি", "বাল্ট" এবং "" (মানে আমাকে সব পেতে পারে) পরিচালনা করতে পারে?
ব্লুচিপ্পি

3

এই হিসাবে একটি সহজ

string[] users = new string[] {"Paul","Steve","Annick","Yannick"};    
var result = from u in users where u.Contains("nn") select u;

ফলাফল -> আনিক, ইয়ানিক



2

আপনি একা পদ্ধতিতে একটি প্রিকেট দিয়ে কল করতে পারেন:

var portCode = Database.DischargePorts
                   .Single(p => p.PortName.Contains("BALTIMORE"))
                   .PortCode;

2
  .Where(e => e.Value.StartsWith("BALTIMORE"))

এটি এসকিউএল এর "লাইক" এর মতো কাজ করে ...


9
না .. না এটি কেবল 'টার্ম%' এর মতো কাজ করে না যা সম্পূর্ণ অপারেটরের মতো কাজ করা অনেক দূরে এবং ওয়াইল্ডকার্ড সমর্থন করে না
ক্রিস ম্যাকগ্রা


0
   public static class StringEx
    {
        public static bool Contains(this String str, string[] Arr, StringComparison comp)
        {
            if (Arr != null)
            {
                foreach (string s in Arr)
                {
                    if (str.IndexOf(s, comp)>=0)
                    { return true; }
                }
            }

            return false;
        }

        public static bool Contains(this String str,string[] Arr)
        {
            if (Arr != null)
            {
                foreach (string s in Arr)
                {
                    if (str.Contains(s))
                    { return true; }
                }
            }

            return false;
        }
    }


var portCode = Database.DischargePorts
                   .Single(p => p.PortName.Contains( new string[] {"BALTIMORE"},  StringComparison.CurrentCultureIgnoreCase) ))
                   .PortCode;

0

স্ট্রিং অবজেক্ট এক্সটেনশন পদ্ধতিগুলিতে কেবল যুক্ত করুন।

public static class StringEx
{
    public static bool Contains(this String str, string[] Arr, StringComparison comp)
    {
        if (Arr != null)
        {
            foreach (string s in Arr)
            {
                if (str.IndexOf(s, comp)>=0)
                { return true; }
            }
        }

        return false;
    }

    public static bool Contains(this String str,string[] Arr)
    {
        if (Arr != null)
        {
            foreach (string s in Arr)
            {
                if (str.Contains(s))
                { return true; }
            }
        }

        return false;
    }
}

ব্যবহার:

use namespase that contains this class;

var sPortCode = Database.DischargePorts
            .Where(p => p.PortName.Contains(new string [] {"BALTIMORE"},  StringComparison.CurrentCultureIgnoreCase) )
            .Single().PortCode;

0

@ অ্যাডোব্রিজকের দুর্দান্ত কাস্টম LIKEফাংশন ছিল - আমি এর IEnumerableসংস্করণটি কেবল ভাগ করে নিতে চেয়েছিলাম ।

public static class LinqEx
{
    private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
    private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });

    private static Func<TSource, bool> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value)
    {
        var param = Expression.Parameter(typeof(TSource), "t");
        var propertyInfo = GetPropertyInfo(property);
        var member = Expression.Property(param, propertyInfo.Name);

        var startWith = value.StartsWith("%");
        var endsWith = value.EndsWith("%");

        if (startWith)
            value = value.Remove(0, 1);

        if (endsWith)
            value = value.Remove(value.Length - 1, 1);

        var constant = Expression.Constant(value);
        Expression exp;

        if (endsWith && startWith)
        {
            exp = Expression.Call(member, ContainsMethod, constant);
        }
        else if (startWith)
        {
            exp = Expression.Call(member, EndsWithMethod, constant);
        }
        else if (endsWith)
        {
            exp = Expression.Call(member, StartsWithMethod, constant);
        }
        else
        {
            exp = Expression.Equal(member, constant);
        }

        return Expression.Lambda<Func<TSource, bool>>(exp, param).Compile();
    }

    public static IEnumerable<TSource> Like<TSource, TMember>(this IEnumerable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value)
    {
        return source.Where(LikeExpression(parameter, value));
    }


    private static PropertyInfo GetPropertyInfo(Expression expression)
    {
        var lambda = expression as LambdaExpression;
        if (lambda == null)
            throw new ArgumentNullException("expression");

        MemberExpression memberExpr = null;

        switch (lambda.Body.NodeType)
        {
            case ExpressionType.Convert:
                memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
                break;
            case ExpressionType.MemberAccess:
                memberExpr = lambda.Body as MemberExpression;
                break;
        }

        if (memberExpr == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");


        var output = memberExpr.Member as PropertyInfo;

        if (output == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");

        return output;
    }
}

0

এক্সটেনশন লিনক / এসকিউএল এর মতো

লাইক এক্সটেনশন ক্লাস

নেট 5 তে পরীক্ষিত

 public static class LikeExtension {

    private static string ColumnDataBase<TEntity, TKey>(IModel model, Expression<Func<TEntity, TKey>> predicate) where TEntity : class {

        ITable table = model
            .GetRelationalModel()
            .Tables
            .First(f => f
                .EntityTypeMappings
                .First()
                .EntityType == model
                .FindEntityType(predicate
                    .Parameters
                    .First()
                .Type
            ));

        string column = (predicate.Body as MemberExpression).Member.Name;
        string columnDataBase = table.Columns.First(f => f.PropertyMappings.Count(f2 => f2.Property.Name == column) > 0).Name;

        return columnDataBase;

    }

    public static IQueryable<TEntity> Like<TEntity, TKey>(this DbContext context, Expression<Func<TEntity, TKey>> predicate, string text) where TEntity : class {

        string columnDataBase = ColumnDataBase(context.Model, predicate);
        return context.Set<TEntity>().FromSqlRaw(context.Set<TEntity>().ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text);

    }

    public static async Task<IEnumerable<TEntity>> LikeAsync<TEntity, TKey>(this DbContext context, Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) where TEntity : class {

        string columnDataBase = ColumnDataBase(context.Model, predicate);
        return await context.Set<TEntity>().FromSqlRaw(context.Set<TEntity>().ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text).ToListAsync(cancellationToken);

    }

    public static async Task<IEnumerable<TEntity>> LikeAsync<TEntity, TKey>(this IQueryable<TEntity> query, Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) where TEntity : class {

        DbSet<TEntity> entities = query as DbSet<TEntity>;
        string columnDataBase = ColumnDataBase(entities.EntityType.Model, predicate);
        return await entities.FromSqlRaw(query.ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text).ToListAsync(cancellationToken);

    }

    public static IQueryable<TEntity> Like<TEntity, TKey>(this IQueryable<TEntity> query, Expression<Func<TEntity, TKey>> predicate, string text) where TEntity : class {

        DbSet<TEntity> entities = query as DbSet<TEntity>;
        string columnDataBase = ColumnDataBase(entities.EntityType.Model, predicate);
        return entities.FromSqlRaw(query.ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text);

    }

}

ভান্ডার

    public async Task<IEnumerable<TEntity>> LikeAsync<TKey>(Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) {

        return await context.LikeAsync(predicate, text, cancellationToken);

    }

    public IQueryable<TEntity> Like<TKey>(Expression<Func<TEntity, TKey>> predicate, string text) {

        return context.Like(predicate, text);

    }

ব্যবহার

 IQueryable<CountryEntity> result = countryRepository
     .Like(k => k.Name, "%Bra[sz]il%") /*Use Sync*/
     .Where(w => w.DateRegister < DateTime.Now) /*Example*/
     .Take(10); /*Example*/

বা

 IEnumerable<CountryEntity> result = await countryRepository
     .LikeAsync(k => k.Name, "%Bra[sz]il%", cancellationToken); /*Use Async*/

বা

 IQueryable<CountryEntity> result = context.Countries
     .Like(k => k.Name, "%Bra[sz]il%")
     .Where(w => w.Name != null); /*Example*/

বা

 List<CountryEntity> result2 = await context.Countries
     .Like(k => k.Name, "%Bra[sz]il%")
     .Where(w => w.Name != null) /*Example*/
     .ToListAsync(); /*Use Async*/

বা

 IEnumerable<CountryEntity> result3 = await context.Countries
     .Where(w => w.Name != null)
     .LikeAsync(k => k.Name, "%Bra[sz]il%", cancellationToken); /*Use Async*/

0

আপনি। নেট 5 এ পরীক্ষা করা EF ফাংশনটিও ব্যবহার করতে পারেন

public async Task<IEnumerable<District>> SearchDistrict(string query, int stateId)
        {
            return await _dbContext
                .Districts
                .Include(s => s.State)
                .Where(s => s.StateId == stateId && EF.Functions.Like(s.Name, "$%{query}%"))
                .AsNoTracking()
                .ToListAsync();
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.