আমি কীভাবে এই ক্যোয়ারীটি পরিবর্তন করব যাতে এটি সমস্ত ইউজারগ্রুপকে ফিরিয়ে দেয়?
from u in usergroups
from p in u.UsergroupPrices
select new UsergroupPricesList
{
UsergroupID = u.UsergroupID,
UsergroupName = u.UsergroupName,
Price = p.Price
};
আমি কীভাবে এই ক্যোয়ারীটি পরিবর্তন করব যাতে এটি সমস্ত ইউজারগ্রুপকে ফিরিয়ে দেয়?
from u in usergroups
from p in u.UsergroupPrices
select new UsergroupPricesList
{
UsergroupID = u.UsergroupID,
UsergroupName = u.UsergroupName,
Price = p.Price
};
উত্তর:
এমএসডিএন থেকে অভিযোজিত, ইএফ 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)
};
from x in gj.DefaultIfEmpty()
হয়ে from p in gj.DefaultIfEmpty()
। ডকস.মাইক্রোসফট.ওন
এটি ওভারকিলের কিছুটা হলেও হতে পারে তবে আমি একটি এক্সটেনশন পদ্ধতি লিখেছিলাম, সুতরাং আপনি সিনট্যাক্সটি 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);
}
}
}
দয়া করে আপনার জীবনকে আরও সহজ করুন (দলে যোগদানের জন্য ব্যবহার করবেন না):
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)
};
Price = ugp.Price
ব্যর্থ হতে পারে যদি Price
একটি অ-অযোগ্য সম্পত্তি হয় এবং বাম জোড় কোনও ফলাফল দেয় না যদিও।
ugp == NULL
এবং এর জন্য একটি ডিফল্ট মান সেট করতে পারি Price
।
আপনি যদি পদ্ধতি কল স্বরলিপিটি পছন্দ করেন তবে আপনি 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 এবং আরও বাম যোগ দেয় (বাম যোগদানকারী স্রষ্টা ব্যবহারকারী এবং ইনিশিয়েটর ব্যবহারকারী)
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
};
আমি প্রধান মডেলটিতে 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
});
.DefaultIfEmpty()
: db.Complains
খালি থাকলে তা কেবল প্রভাবিত করে । db.Complains.Where(...).OrderBy(...).Select(x => new { ..., MemberName = x.Member != null ? x.Member.Name : string.Empty, ... })
, কোনও ছাড়াই .DefaultIfEmpty()
, ইতিমধ্যে বাম জোড় ( Member
সম্পত্তিটিকে optionচ্ছিক হিসাবে চিহ্নিত করা হয়েছে) ধরে নেওয়া হবে perform
যদি ইউজার গ্রুপের ইউজারগ্রুপ প্রাইসস টেবিলের সাথে অনেকগুলি সম্পর্ক থাকে তবে EF এ একবার সম্পর্কটিকে কোডের মতো সংজ্ঞায়িত করা হলে:
//In UserGroups Model
public List<UserGroupPrices> UserGrpPriceList {get;set;}
//In UserGroupPrices model
public UserGroups UserGrps {get;set;}
আপনি কেবল এই দ্বারা বামে যোগদানের ফলাফলটি টানতে পারেন:
var list = db.UserGroupDbSet.ToList();
বাম টেবিলের জন্য আপনার ডিবিসেট ধরে নেওয়া হচ্ছে ইউজারগ্রুপডিবিসেট, এতে ইউজারগ্রাপপ্রাইসলিস্ট অন্তর্ভুক্ত থাকবে যা ডান টেবিলের সাথে সম্পর্কিত সমস্ত রেকর্ডের একটি তালিকা।