How to debug query in c# program? - c#

I want to write query more efficient.
I do not want before the end of the query, the list of data to extract.
var UserTimeLineNews = (from l in _newsService.NewsQuery()
where l.UserId == UserId && l.IsActive == true
orderby l.CreateDate descending
select new UserTimeLine
{
EventDate = l.CreateDate,
CreateDate = l.CreateDate,
NewsId = l.NewsId,
TimeLineType = TimeLineType.CreateNews,
Title = l.Title,
Abstract = l.NewsAbstract,
CommentCount = l.CommentCount,
LikeCount = l.LikeCount,
ViewsCount = l.ViewsCount,
Storyteller = l.Storyteller
}).AsQueryable();//Take(NumberOfNews).ToList();
var UserTimeLineLikeNews = (from l in _likeNewsService.LikeNewsQueryable()
where l.UserId == UserId
orderby l.CreateDate descending
select new UserTimeLine
{
EventDate = l.CreateDate,
CreateDate = l.CreateDate,
NewsId = l.NewsId,
TimeLineType = TimeLineType.LikeNews,
Title = l.News.Title,
Abstract = l.News.NewsAbstract,
CommentCount = l.News.CommentCount,
LikeCount = l.News.LikeCount,
ViewsCount = l.News.ViewsCount,
Storyteller = l.News.Storyteller
}).AsQueryable();//Take(NumberOfNews).ToList();
var UserTimeLineComments = (from l in _commentService.CommentQueryable()
where l.UserId == UserId && l.IsActive == true
orderby l.CreateDate descending
select new UserTimeLine
{
EventDate = l.CreateDate,
CreateDate = l.CreateDate,
NewsId = l.NewsId,
TimeLineType = TimeLineType.Comment,
Title = l.News.Title,
Abstract = l.News.NewsAbstract,
CommentContent = l.Content,
CommentCount = l.News.CommentCount,
LikeCount = l.News.LikeCount,
ViewsCount = l.News.ViewsCount,
Storyteller = l.News.Storyteller
}).AsQueryable();//Take(NumberOfNews).ToList();
var item = (UserTimeLineNews
.Union(UserTimeLineLikeNews)
.Union(UserTimeLineComments))
.OrderByDescending(e => e.EventDate)
.Distinct()
.Take(NumberOfNews)
.ToList();
After running the following error appears
Error:
The type 'UserTimeLine' appears in two structurally incompatible initializations within a single LINQ to Entities query.
A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.

The first two queries don't initialize the CommentContent property. Add that to the initializer in the first two queries (or remove it in the last query) and the final query should work.

Related

Ordering issue with Groupby in Linq

I am facing issues in using order by with group by in linq queries. when I apply group by after order by the ordering is being lost using the following code.
I want to sort all the conversations where type is in ascending. I doubt using Select(x=>x.FirstOrDefault()) is creating some issue.
I am using LINQ queries like this
DateTime? convStartDate = DateTime.Now.AddDays(-90);
DateTime? convEndDate = DateTime.Now;
var limit = 1000;
var offset = 0;
var query = (from conversation in db.textMessagesconversation
join msgParticipants in db.participants on conversation.Id equals msgParticipants.ConversationId
join msg in db.MsgMessages on conversation.Id equals msg.ConversationId
where msgParticipants.UserId == userID && ( (String.IsNullOrEmpty(convStartDate.ToString()) || msg.DateCreatedTime >= convStartDate)
&& (String.IsNullOrEmpty(convEndDate.ToString()) || msg.DateCreatedTime <= convEndDate)
select new RawConversation
{
LastMessageContent = msg.Content,
LastMessageDateTime = msg.DateCreatedTime,
IsAttachment = msg.IsAttachment,
SenderId = msg.SenderId,
MessageId = msg.Id,
Type = conversation.Type,
Name = conversation.Name,
Id = conversation.Id
});
query = query.OrderBy(x => x.Type);
var textmessagesList= query.GroupBy(x=>x.Id).Select(x=>x.FirstOrDefault()).Skip(offset).Take(limit).ToList();

Add conditions after muilti join LINQ expression

I've got a Linq query with 5 joins/tables, with predefined conditions.
Because I need the query multiple times I've created a function which returns the default LINQ query as an IQueryable.
public static IQueryable<MroomLinqModel> GetDefaultQuery(CustomerContext CustomerCtx)
{
var Mrooms = (from mr in CustomerCtx.Mrooms
join m in CustomerCtx.Moves on mr.MoveId equals m.MoveId
join mg in CustomerCtx.mgroup on m.MgroupId equals mg.MgroupId
join s in CustomerCtx.Status on m.StatusId equals s.StatusId
join rt in CustomerCtx.Roomtypes on mr.RoomtypeId equals rt.Key
join g in CustomerCtx.Guests on m.Mgroup.GuestId equals g.GuestId
where
Math.Abs(mg.Status) != (int)IResStatus.InComplete &&
s.Visible
select new MroomLinqModel
{
OpenDepositPayments = mg.DepositPayments.Any(dp => !dp.Paid),
RoomHidden = (mr.RoomId == null ? true : mr.Room.Hidden),
StatusVisible = s.Visible,
MroomId = mr.MroomId,
MoveId = m.MoveId,
MgroupId = mg.MgroupId,
StatusId = s.StatusId,
StatusFlags = s.Flags,
BackgroundColor = s.Background_Argb,
TextColor = s.Foreground_Argb,
PersonCount = m.Movegroups.Sum(m => m.PersonCount),
MoveCount = mg.Moves.Count(),
RoomId = mr.RoomId,
PMSMroomId = mr.PMS_Id,
PMSMoveId = m.PMS_Id,
PMSMgroupId = mg.MgroupId_Casablanca,
From = mr.From,
Until = mr.Until,
EditableState = m.EditableState,
MroomStatus = mr.Status,
RoomtypeUsage = mr.Roomtype.Usage,
BookingReference = mg.ReferenceNumber,
Guest = g
});
return Mrooms;
}
Now I would like to add some conditions afterwards like:
Query = GetDefaultQuery.Where(q => !q.RoomHidden && q.From <= dtLoadEnd && dtLoadStart <= q.Until);
Query = Query.Where(q => q.RoomtypeUsage == RoomtypeUsageType.Roomplan);
This works fine but takes a lot more time to execute as if I add all conditions directly to the first LINQ query.
How do I form the query to access the original tables and generate a fast query?
Since all your condition match the table where you are joining the other tables you can add the conditions before your multi join, I got 2 suggestions for you, either create another method that filters your conditions predefined or add to your method optional filters like so :
public static IQueryable<MroomLinqModel> GetDefaultQuery(CustomerContext CustomerCtx, bool? roomHidden, DateTime? dtLoadEnd
/* you can add more parameters but for demonstrations purposes i'm only describing this 2*/)
{
var query = CustomerCtx.Mrooms;
if(roomHidden.HasValue)
{
query = query.Where( q=>q.From == roomHidden.Value)
}
if(dtLoadEnd .HasValue)
{
query = query.Where( q=>q.RoomHidden <= dtLoadEnd.Value)
}
// you can add more conditions
var Mrooms = (from query
join m in CustomerCtx.Moves on mr.MoveId equals m.MoveId
join mg in CustomerCtx.mgroup on m.MgroupId equals mg.MgroupId
join s in CustomerCtx.Status on m.StatusId equals s.StatusId
join rt in CustomerCtx.Roomtypes on mr.RoomtypeId equals rt.Key
join g in CustomerCtx.Guests on m.Mgroup.GuestId equals g.GuestId
where
Math.Abs(mg.Status) != (int)IResStatus.InComplete &&
s.Visible
select new MroomLinqModel
{
OpenDepositPayments = mg.DepositPayments.Any(dp => !dp.Paid),
RoomHidden = (mr.RoomId == null ? true : mr.Room.Hidden),
StatusVisible = s.Visible,
MroomId = mr.MroomId,
MoveId = m.MoveId,
MgroupId = mg.MgroupId,
StatusId = s.StatusId,
StatusFlags = s.Flags,
BackgroundColor = s.Background_Argb,
TextColor = s.Foreground_Argb,
PersonCount = m.Movegroups.Sum(m => m.PersonCount),
MoveCount = mg.Moves.Count(),
RoomId = mr.RoomId,
PMSMroomId = mr.PMS_Id,
PMSMoveId = m.PMS_Id,
PMSMgroupId = mg.MgroupId_Casablanca,
From = mr.From,
Until = mr.Until,
EditableState = m.EditableState,
MroomStatus = mr.Status,
RoomtypeUsage = mr.Roomtype.Usage,
BookingReference = mg.ReferenceNumber,
Guest = g
});
return Mrooms;
}
expecting that CustomerCtx.Mrooms is a DbSet<Mroom> and that Mroom looks like :
public class Mroom {
public int MroomId {get; set;}
[ForeignKey("Move")]
public int MoveId {get; set;} //FK
public virtual Move Move {get; set;} //Navigation property
//configuration may be needed cf annotation
[ForeignKey("Status")]
public int StatusId {get; set;}
public virtual Status Status {get; set;}
//... Mgroup, Guest, ...
}
If it is not the case I suggest you yo refactor your code to use navigation properties.
Then you may use PredicateBuilder of linqkit as follow:
public static IQueryable<MroomLinqModel> GetDefaultQuery(CustomerContext CustomerCtx, Expression<Function<Mroom, bool>> q)
{
Expression<Function<Mroom, bool>> w = PredicateBuilder.New<Mroom>
(s => Math.Abs(s.Mgroup.Status) != (int)IResStatus.InComplete &&
s.Visible);
w = w.And(q);
return
CustomerCtx.Mrooms.
Where(w.Expand()).
Select( x => new MroomLinqModel
{
OpenDepositPayments = x.Mgroup.DepositPayments.Any(dp => !dp.Paid),
RoomHidden = (x.RoomId == null ? true : x.Room.Hidden),
StatusVisible = x.Status.Visible,
MroomId = x.MroomId,
MoveId = x.MoveId,
MgroupId = x.MgroupId,
StatusId = x.Status.StatusId,
StatusFlags = x.Status.Flags,
BackgroundColor = x.Status.Background_Argb,
TextColor = x.Status.Foreground_Argb,
PersonCount = x.Move.Movegroups.Sum(m => m.PersonCount),
MoveCount = x.Mgroup.Moves.Count(),
RoomId = x.RoomId,
PMSMroomId = x.PMS_Id,
PMSMoveId = x.Move.PMS_Id,
PMSMgroupId = x.Mgroup.MgroupId_Casablanca,
From = x.From,
Until = x.Until,
EditableState = x.Move.EditableState,
MroomStatus = x.Move.Status,
RoomtypeUsage = mr.Roomtype.Usage,
BookingReference = x.Mgroup.ReferenceNumber,
Guest = x.Guest
}
);
}
and use it as:
GetDefaultQuery(ctx, q => !q.RoomHidden && q.From <= dtLoadEnd && dtLoadStart <= q.Until);
and or
Expression<Function<Mroom, bool>> w = PredicateBuilder.New<Mroom>(q =>
!q.RoomHidden && q.From <= dtLoadEnd && dtLoadStart <= q.Until);
//some logic
w = w.And(q => q.RoomtypeUsage == RoomtypeUsageType.Roomplan);
GetDefaultQuery(ctx, w);

Linq Include Extra Column in GroupBy Selection

I have a "ReactionSimple" column that I'd like to include in the GroupBy selection but when I include it in the Group By it throws off the returned row count in a big way. Is there a way to include the commented out column in the final grouped selection without throwing off the result count. I'm a LINQ noob.
var reactivityResults = new List<ReactivityResultViewModel>();
var reactivityResults2 = new List<ReactivityResultViewModel>();
var classifications = GetMaterialClassifications(test.TestType);
var antigens = _db.Antigens.ToList();
if (test.ResultSets.Any())
{
var testResult = test.ResultSets.FirstOrDefault();
var dateReported = testResult.DateReported;
var details = testResult.ResultSetDetails.ToList();
if (details.Any())
{
reactivityResults = (from d in details
join a in _db.Antigens on d.AntigenId equals a.AntigenId
join ma in _db.MaterialAntigens on a.AntigenId equals ma.AntigenId
join md in _db.MaterialDefs on ma.MaterialDefId equals md.MaterialDefId
join c in classifications on md.MaterialId equals c.MaterialId
select new ReactivityResultViewModel
{
MaterialId = c.MaterialId,
MaterialName = c.MaterialName,
IsActive = md.IsActive,
ReactionSimple = (ReactionTypeEnum)d.ReactionSimple,
TestId = test.TestId,
AccessionId = test.AccessionId,
PatientFirstName = test.Patient.Party.NameFirst,
PatientLastName = test.Patient.Party.NameLast,
TestType = (TestTypeNoFlagsEnum)test.TestType,
DateReported = dateReported,
ManufacturerId = c.ManufacturerId,
ManufacturerName = c.ManufacturerName
})
.OrderBy(x => x.MaterialName)
.ToList();
var sreactivityResults2 = reactivityResults
.GroupBy(x => new {
x.MaterialId, x.AccessionId, x.DateReported,
x.IsActive, x.ManufacturerId, x.ManufacturerName,
x.MaterialName, x.PatientFirstName, x.PatientLastName,
x.TestId, x.TestType,
//x.ReactionSimple
})
.Select(x => new ReactivityResultViewModel
{
MaterialId = x.Key.MaterialId,
MaterialName = x.Key.MaterialName,
IsActive = x.Key.IsActive,
//ReactionSimple = x.Key.ReactionSimple,
TestId = test.TestId,
AccessionId = test.AccessionId,
PatientFirstName = test.Patient.Party.NameFirst,
PatientLastName = test.Patient.Party.NameLast,
TestType = (TestTypeNoFlagsEnum)test.TestType,
DateReported = dateReported,
ManufacturerId = x.Key.ManufacturerId,
ManufacturerName = x.Key.ManufacturerName
})
.ToList();
var sd2 = sreactivityResults2.ToList();
}
return reactivityResults;

Returning List value using linq C#

Actually I want to return the data from different lists based on Date. When i'm using this i'm getting data upto #Var result but i'm unnable to return the data. The issue with this is i'm getting error #return result. I want to return the data #return result. I'm using Linq C#. Can anyone help me out?
public List<CustomerWiseMonthlySalesReportDetails> GetAllCustomerWiseMonthlySalesReportCustomer()
{
var cbsalesreeport = (from cb in db.cashbilldescriptions
join c in db.cashbills on cb.CashbillId equals c.CashbillId
join p in db.products on cb.ProductId equals p.ProductId
select new
{
Productamount = cb.Productamount,
ProductName = p.ProductDescription,
CashbillDate = c.Date
}).AsEnumerable().Select(x => new ASZ.AmoghGases.Model.CustomerWiseMonthlySalesReportDetails
{
Productdescription = x.ProductName,
Alldates = x.CashbillDate,
TotalAmount = x.Productamount
}).ToList();
var invsalesreeport = (from inv in db.invoices
join invd in db.invoicedeliverychallans on inv.InvoiceId equals invd.InvoiceId
select new
{
Productamount = invd.Total,
ProductName = invd.Productdescription,
InvoiceDate = inv.Date
}).AsEnumerable().Select(x => new ASZ.AmoghGases.Model.CustomerWiseMonthlySalesReportDetails
{
Productdescription = x.ProductName,
Alldates = x.InvoiceDate,
TotalAmount = x.Productamount
}).ToList();
var abc = cbsalesreeport.Union(invsalesreeport).ToList();
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription } into grp
select new { Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
**return result;**
}
You can either convert your result to a List before returning it using return result.ToList() or make your method return an IEnumerable<CustomerWiseMonthlySalesReportDetails> instead of List.
As your result is an enumeration of anonymous types you have to convert them to your CustomerWiseMonthlySalesReportDetails-type first:
select new CustomerWiseMonthlySalesReportDetails{ Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
Assuming your type has exactly the members returned by the select.
EDIT: So your code should look like this:
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription } into grp
select new CustomerWiseMonthlySalesReportDetails{ Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
return result.ToList();
You can assume Alldates property if is date of one of groups that month of date is in right place:
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription }
into grp
select new CustomerWiseMonthlySalesReportDetails{
Productdescription = grp.Key.Product,
TotalAmount = grp.Sum(i => i.TotalAmount),
Alldates =grp.First(i=>i.Alldates ) })
.ToList();

Not getting the difference between two list by using linq

I have two lists as follows:
var SeparatedEmployees = (from s in DataContext.HRM_EMP_TRMN.AsEnumerable()
where s.TRMN_FINL_STUS == "SA" && ((Convert.ToDateTime(s.TRMN_EFCT_DATE)).Year).ToString() == Year && ((Convert.ToDateTime(s.TRMN_EFCT_DATE)).Month).ToString() == HRMD_COMMON.ReturnMonthName(Month)
join e in DataContext.VW_HRM_EMPLOYEE on s.EMP_CODE equals e.EMP_CODE
where e.ACTIVE_STATUS == "A"
select new HRM_EMP_FINL_STMT_MSTModel
{
EMP_CODE = s.EMP_CODE,
EMP_NAME = e.EMP_NAME,
DIVI_CODE = e.DIVI_CODE,
DIVI_NAME = e.DIVI_NAME,
EMP_DESIG_CODE = e.EMP_DESIG_CODE,
EMP_DESIG_NAME = e.EMP_DESIG_NAME,
JOINING_DATE = HRMD_COMMON.ReturnOnlyDate(Convert.ToDateTime(e.JOINING_DATE)),
TRMN_TYPE = HRMD_COMMON.ReturnTerminationType(s.TRMN_TYPE),
TRMN_EFCT_DATE = HRMD_COMMON.ReturnOnlyDate(Convert.ToDateTime(s.TRMN_EFCT_DATE)),
LAST_SAL_PROS_MON = HRMD_COMMON.ReturnMonthName(s.LAST_SAL_PROS_MON),
FINL_STMT_REM = s.TRMN_REM
}).ToList();
var ConfirmedEmployees = (from c in DataContext.HRM_EMP_FINL_STMT_MST.AsEnumerable()
where ((Convert.ToDateTime(c.FINL_STMT_DATE)).Year).ToString() == Year && ((Convert.ToDateTime(c.FINL_STMT_DATE)).Month).ToString() == HRMD_COMMON.ReturnMonthName(Month)
join e in DataContext.VW_HRM_EMPLOYEE on c.EMP_CODE equals e.EMP_CODE
join s in DataContext.HRM_EMP_TRMN on c.EMP_CODE equals s.EMP_CODE
select new HRM_EMP_FINL_STMT_MSTModel
{
EMP_CODE = s.EMP_CODE,
EMP_NAME = e.EMP_NAME,
DIVI_CODE = e.DIVI_CODE,
DIVI_NAME = e.DIVI_NAME,
EMP_DESIG_CODE = e.EMP_DESIG_CODE,
EMP_DESIG_NAME = e.EMP_DESIG_NAME,
JOINING_DATE = HRMD_COMMON.ReturnOnlyDate(Convert.ToDateTime(e.JOINING_DATE)),
TRMN_TYPE = HRMD_COMMON.ReturnTerminationType(s.TRMN_TYPE),
TRMN_EFCT_DATE = HRMD_COMMON.ReturnOnlyDate(Convert.ToDateTime(s.TRMN_EFCT_DATE)),
LAST_SAL_PROS_MON = HRMD_COMMON.ReturnMonthName(s.LAST_SAL_PROS_MON),
FINL_STMT_REM = s.TRMN_REM
}).ToList();
Tyring to remove the items from the first list, which are also in second list.
var FinalSeparatedEmployees = (from item in SeparatedEmployees
where !ConfirmedEmployees.Contains(item)
select item).ToList();
Tried this one too:
FinalSeparatedEmployees = SeparatedEmployees.Except(ConfirmedEmployees).ToList<HRM_EMP_FINL_STMT_MSTModel>();
But not getting the accurate result. What I'm missing? Thanks.
Its better to use EMP_CODE because your objects are not comparable.
var ids = ConfirmedEmployees.Select(x => x.EMP_CODE).ToList();
var FinalSeparatedEmployees = (from item in SeparatedEmployees
where !ids.Contains(item.EMP_CODE)
select item).ToList();

Categories