আমি কীভাবে এই ক্যোয়ারীটি পরিবর্তন করব যাতে এটি সমস্ত ইউজারগ্রুপকে ফিরিয়ে দেয়?
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();
বাম টেবিলের জন্য আপনার ডিবিসেট ধরে নেওয়া হচ্ছে ইউজারগ্রুপডিবিসেট, এতে ইউজারগ্রাপপ্রাইসলিস্ট অন্তর্ভুক্ত থাকবে যা ডান টেবিলের সাথে সম্পর্কিত সমস্ত রেকর্ডের একটি তালিকা।