সত্তা ফ্রেমওয়ার্ক যোগদান যোগদান


84

আমি কীভাবে এই ক্যোয়ারীটি পরিবর্তন করব যাতে এটি সমস্ত ইউজারগ্রুপকে ফিরিয়ে দেয়?

from u in usergroups
from p in u.UsergroupPrices
select new UsergroupPricesList
{
UsergroupID = u.UsergroupID,
UsergroupName = u.UsergroupName,
Price = p.Price
};

4
সম্ভবত এটি সাহায্য করতে পারে। এটি এখানে এসও
মেনাহেম

উত্তর:


135

এমএসডিএন থেকে অভিযোজিত, ইএফ 4 ব্যবহার করে কীভাবে বামে যোগ দিতে হবে

var query = from u in usergroups
            join p in UsergroupPrices on u.UsergroupID equals p.UsergroupID into gj
            from x in gj.DefaultIfEmpty()
            select new { 
                UsergroupID = u.UsergroupID,
                UsergroupName = u.UsergroupName,
                Price = (x == null ? String.Empty : x.Price) 
            };

4
আমি gj.DefaultIfEmpty () শেষের চেয়ে আরও বেশি পছন্দ করি কারণ আমি যেখানে x ব্যবহার করতে পারি বা নির্বাচন করতে পারি!
গ্যারি

4
আপনি 'এক্স x থেকে gj.DefaultIfEmpty ()' লাইনটি ব্যাখ্যা করতে পারেন?
অ্যালেক্স ড্রেসকো

@ অ্যালেক্সড্রেসকো এই অংশটি যোগদানের সমস্ত ফলাফল নিয়েছে এবং যার ডান হাতের মূল্য নেই তাদের জন্য আপনাকে শূন্য দেয় (অবজেক্টের নਾਲ হওয়ার কারণে ডিফল্ট)। HTH
মনহেম

4
দুটি টেবিলের বেশি হলে কী হবে?
মোহাম্মদহসিন আর

4
ইফকোরের সাথে এটি কিছুটা পরিবর্তন হয়েছে; from x in gj.DefaultIfEmpty()হয়ে from p in gj.DefaultIfEmpty()ডকস.মাইক্রোসফট.ওন
সেফ /

33

এটি ওভারকিলের কিছুটা হলেও হতে পারে তবে আমি একটি এক্সটেনশন পদ্ধতি লিখেছিলাম, সুতরাং আপনি সিনট্যাক্সটি LeftJoinব্যবহার করে একটি পদ্ধতি করতে পারেন Join(কমপক্ষে পদ্ধতিতে কল স্বরলিপিতে):

persons.LeftJoin(
    phoneNumbers,
    person => person.Id,
    phoneNumber => phoneNumber.PersonId,
    (person, phoneNumber) => new
        {
            Person = person,
            PhoneNumber = phoneNumber?.Number
        }
);

আমার কোডটি বর্তমানের এক্সপ্রেশন ট্রিটিতে একটি GroupJoinএবং SelectManyকল যুক্ত করা ছাড়া আর কিছুই করে না । তবুও, এটি বেশ জটিল দেখাচ্ছে কারণ resultSelectorলিনকিউ-টু-সত্তা দ্বারা পুরো গাছটিকে অনুবাদযোগ্য রাখার জন্য আমাকে প্যারামিটারে ব্যবহারকারী দ্বারা বর্ণিত অভিব্যক্তি গাছটি নিজেই তৈরি করতে হবে এবং এক্সপ্রেশন গাছটি পরিবর্তন করতে হবে।

public static class LeftJoinExtension
{
    public static IQueryable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(
        this IQueryable<TOuter> outer,
        IQueryable<TInner> inner,
        Expression<Func<TOuter, TKey>> outerKeySelector,
        Expression<Func<TInner, TKey>> innerKeySelector,
        Expression<Func<TOuter, TInner, TResult>> resultSelector)
    {
        MethodInfo groupJoin = typeof (Queryable).GetMethods()
                                                 .Single(m => m.ToString() == "System.Linq.IQueryable`1[TResult] GroupJoin[TOuter,TInner,TKey,TResult](System.Linq.IQueryable`1[TOuter], System.Collections.Generic.IEnumerable`1[TInner], System.Linq.Expressions.Expression`1[System.Func`2[TOuter,TKey]], System.Linq.Expressions.Expression`1[System.Func`2[TInner,TKey]], System.Linq.Expressions.Expression`1[System.Func`3[TOuter,System.Collections.Generic.IEnumerable`1[TInner],TResult]])")
                                                 .MakeGenericMethod(typeof (TOuter), typeof (TInner), typeof (TKey), typeof (LeftJoinIntermediate<TOuter, TInner>));
        MethodInfo selectMany = typeof (Queryable).GetMethods()
                                                  .Single(m => m.ToString() == "System.Linq.IQueryable`1[TResult] SelectMany[TSource,TCollection,TResult](System.Linq.IQueryable`1[TSource], System.Linq.Expressions.Expression`1[System.Func`2[TSource,System.Collections.Generic.IEnumerable`1[TCollection]]], System.Linq.Expressions.Expression`1[System.Func`3[TSource,TCollection,TResult]])")
                                                  .MakeGenericMethod(typeof (LeftJoinIntermediate<TOuter, TInner>), typeof (TInner), typeof (TResult));

        var groupJoinResultSelector = (Expression<Func<TOuter, IEnumerable<TInner>, LeftJoinIntermediate<TOuter, TInner>>>)
                                      ((oneOuter, manyInners) => new LeftJoinIntermediate<TOuter, TInner> {OneOuter = oneOuter, ManyInners = manyInners});

        MethodCallExpression exprGroupJoin = Expression.Call(groupJoin, outer.Expression, inner.Expression, outerKeySelector, innerKeySelector, groupJoinResultSelector);

        var selectManyCollectionSelector = (Expression<Func<LeftJoinIntermediate<TOuter, TInner>, IEnumerable<TInner>>>)
                                           (t => t.ManyInners.DefaultIfEmpty());

        ParameterExpression paramUser = resultSelector.Parameters.First();

        ParameterExpression paramNew = Expression.Parameter(typeof (LeftJoinIntermediate<TOuter, TInner>), "t");
        MemberExpression propExpr = Expression.Property(paramNew, "OneOuter");

        LambdaExpression selectManyResultSelector = Expression.Lambda(new Replacer(paramUser, propExpr).Visit(resultSelector.Body), paramNew, resultSelector.Parameters.Skip(1).First());

        MethodCallExpression exprSelectMany = Expression.Call(selectMany, exprGroupJoin, selectManyCollectionSelector, selectManyResultSelector);

        return outer.Provider.CreateQuery<TResult>(exprSelectMany);
    }

    private class LeftJoinIntermediate<TOuter, TInner>
    {
        public TOuter OneOuter { get; set; }
        public IEnumerable<TInner> ManyInners { get; set; }
    }

    private class Replacer : ExpressionVisitor
    {
        private readonly ParameterExpression _oldParam;
        private readonly Expression _replacement;

        public Replacer(ParameterExpression oldParam, Expression replacement)
        {
            _oldParam = oldParam;
            _replacement = replacement;
        }

        public override Expression Visit(Expression exp)
        {
            if (exp == _oldParam)
            {
                return _replacement;
            }

            return base.Visit(exp);
        }
    }
}

4
এই এক্সটেনশন ফেরোর জন্য ধন্যবাদ।
ফেরার্স

এটি এখনও দুর্দান্ত। ধন্যবাদ!
TheGeekYouNeed

4
এটি নেট ফ্রেমওয়ার্ক ৪.6.২ এর মধ্যে পরীক্ষিত হয়েছে এবং এটি প্রত্যাশার মতো কাজ করে (যেমন একটি বাম আউটরের যোগদান করে)। আমি বিস্মিত হয়েছি যদি এটি NET কোর তে কাজ করে তবে। ধন্যবাদ
আলেক্সি

24

দয়া করে আপনার জীবনকে আরও সহজ করুন (দলে যোগদানের জন্য ব্যবহার করবেন না):

var query = from ug in UserGroups
            from ugp in UserGroupPrices.Where(x => x.UserGroupId == ug.Id).DefaultIfEmpty()
            select new 
            { 
                UserGroupID = ug.UserGroupID,
                UserGroupName = ug.UserGroupName,
                Price = ugp != null ? ugp.Price : 0 //this is to handle nulls as even when Price is non-nullable prop it may come as null from SQL (result of Left Outer Join)
            };

4
দলে দলে যোগদান এড়ানো মতামতের বিষয়, তবে এটি অবশ্যই একটি কার্যকর মতামত। Price = ugp.Priceব্যর্থ হতে পারে যদি Priceএকটি অ-অযোগ্য সম্পত্তি হয় এবং বাম জোড় কোনও ফলাফল দেয় না যদিও।

4
উপরের সাথে একমত হন, তবে দুটিরও বেশি টেবিলের সাথে এই পদ্ধতিটি পড়া এবং বজায় রাখা এত সহজ।
টমাসজ স্কোমরা

4
আমরা পরীক্ষা করতে পারি ugp == NULLএবং এর জন্য একটি ডিফল্ট মান সেট করতে পারি Price
Hp93


4
অসাধারণ! আমি এই সমাধানটি পাঠযোগ্যতার জন্য পছন্দ করি। এছাড়াও, এটি আরও যোগ দেয় (অর্থাত 3 বা ততোধিক টেবিল থেকে) আরও সহজ করে তোলে! আমি এটি সফলভাবে 2 টি বাম যোগদানের (অর্থাৎ 3 টি টেবিল) জন্য ব্যবহার করেছি।
জেরেমি মরেন

4

আপনি যদি পদ্ধতি কল স্বরলিপিটি পছন্দ করেন তবে আপনি SelectManyএকত্রিত ব্যবহার করে বাম জোড়কে বাধ্য করতে পারেন DefaultIfEmpty। কমপক্ষে সত্তা ফ্রেমওয়ার্ক 6 এসকিউএল সার্ভার হিট করাতে। উদাহরণ স্বরূপ:

using(var ctx = new MyDatabaseContext())
{
    var data = ctx
    .MyTable1
    .SelectMany(a => ctx.MyTable2
      .Where(b => b.Id2 == a.Id1)
      .DefaultIfEmpty()
      .Select(b => new
      {
        a.Id1,
        a.Col1,
        Col2 = b == null ? (int?) null : b.Col2,
      }));
}

(নোট এটি MyTable2.Col2ধরণের কলাম int)। উত্পন্ন এসকিউএল এর মত দেখতে পাবেন:

SELECT 
    [Extent1].[Id1] AS [Id1], 
    [Extent1].[Col1] AS [Col1], 
    CASE WHEN ([Extent2].[Col2] IS NULL) THEN CAST(NULL AS int) ELSE  CAST( [Extent2].[Col2] AS int) END AS [Col2]
    FROM  [dbo].[MyTable1] AS [Extent1]
    LEFT OUTER JOIN [dbo].[MyTable2] AS [Extent2] ON [Extent2].[Id2] = [Extent1].[Id1]

আমার জন্য এটি এতে "ক্রস অ্যাপ্লাইওয়াই" দিয়ে অত্যন্ত ধীর গতির ক্যোয়ারী তৈরি করছে।
মেকোহি

2

2 এবং আরও বাম যোগ দেয় (বাম যোগদানকারী স্রষ্টা ব্যবহারকারী এবং ইনিশিয়েটর ব্যবহারকারী)

IQueryable<CreateRequestModel> queryResult = from r in authContext.Requests
                                             join candidateUser in authContext.AuthUsers
                                             on r.CandidateId equals candidateUser.Id
                                             join creatorUser in authContext.AuthUsers
                                             on r.CreatorId equals creatorUser.Id into gj
                                             from x in gj.DefaultIfEmpty()
                                             join initiatorUser in authContext.AuthUsers
                                             on r.InitiatorId equals initiatorUser.Id into init
                                             from x1 in init.DefaultIfEmpty()

                                             where candidateUser.UserName.Equals(candidateUsername)
                                             select new CreateRequestModel
                                             {
                                                 UserName = candidateUser.UserName,
                                                 CreatorId = (x == null ? String.Empty : x.UserName),
                                                 InitiatorId = (x1 == null ? String.Empty : x1.UserName),
                                                 CandidateId = candidateUser.UserName
                                             };

1

আমি প্রধান মডেলটিতে DefaultIfEmpty () কল করে এটি করতে সক্ষম হয়েছি। এটি আমাকে অলস বোঝা সত্তাগুলিতে যোগদানের অনুমতি দেয়, আমার কাছে এটি আরও পাঠযোগ্য বলে মনে হয়:

        var complaints = db.Complaints.DefaultIfEmpty()
            .Where(x => x.DateStage1Complete == null || x.DateStage2Complete == null)
            .OrderBy(x => x.DateEntered)
            .Select(x => new
            {
                ComplaintID = x.ComplaintID,
                CustomerName = x.Customer.Name,
                CustomerAddress = x.Customer.Address,
                MemberName = x.Member != null ? x.Member.Name: string.Empty,
                AllocationName = x.Allocation != null ? x.Allocation.Name: string.Empty,
                CategoryName = x.Category != null ? x.Category.Ssl_Name : string.Empty,
                Stage1Start = x.Stage1StartDate,
                Stage1Expiry = x.Stage1_ExpiryDate,
                Stage2Start = x.Stage2StartDate,
                Stage2Expiry = x.Stage2_ExpiryDate
            });

4
এখানে, আপনার মোটেই প্রয়োজন নেই .DefaultIfEmpty(): db.Complainsখালি থাকলে তা কেবল প্রভাবিত করে । db.Complains.Where(...).OrderBy(...).Select(x => new { ..., MemberName = x.Member != null ? x.Member.Name : string.Empty, ... }), কোনও ছাড়াই .DefaultIfEmpty(), ইতিমধ্যে বাম জোড় ( Memberসম্পত্তিটিকে optionচ্ছিক হিসাবে চিহ্নিত করা হয়েছে) ধরে নেওয়া হবে perform

1

যদি ইউজার গ্রুপের ইউজারগ্রুপ প্রাইসস টেবিলের সাথে অনেকগুলি সম্পর্ক থাকে তবে EF এ একবার সম্পর্কটিকে কোডের মতো সংজ্ঞায়িত করা হলে:

//In UserGroups Model
public List<UserGroupPrices> UserGrpPriceList {get;set;}

//In UserGroupPrices model
public UserGroups UserGrps {get;set;}

আপনি কেবল এই দ্বারা বামে যোগদানের ফলাফলটি টানতে পারেন:

var list = db.UserGroupDbSet.ToList();

বাম টেবিলের জন্য আপনার ডিবিসেট ধরে নেওয়া হচ্ছে ইউজারগ্রুপডিবিসেট, এতে ইউজারগ্রাপপ্রাইসলিস্ট অন্তর্ভুক্ত থাকবে যা ডান টেবিলের সাথে সম্পর্কিত সমস্ত রেকর্ডের একটি তালিকা।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.