Debug Lambda expressions in C# - c#

I am querying a SQL Server database from my ASP.net application in C#. Following is a part of my database schema.
I wrote following expression to get data from the database.
var query = db.DBMovies.Where(ent => ent.Id == Id).Join(db.DBCategories,
r => r.Id,
l => l.CategoryId,
(r, l) => new
{
Id = r.Id,
MovieName = r.Name,
Year = r.Year,
Category = r.Genre,
PosterURL = r.PosterURL,
});
foreach (var movie in query)
{
//something
}
In the part ent.Id == Id, the Id in the right refers to a parameter value. I referred this tutorial, but when I execute this, the execution does not get inside the foreach loop. I created a breakpoint inside the foreach loop and noticed that it didn't hit. Can somebody help me to find out the issue? And please suggest a way to quick watch the values returned by a lambda expression if possible.
Thank you.
Edit:
I changed the query as I have made a huge mistake first time, but I don't see any success even now.
var query = db.DBMovieToCategory.Where(ent => ent.CategoryId == Id).Join(db.DBMovies,
r => r.MovieId,
l => l.Id,
(r, l) => new
{
Id = l.Id,
MovieName = l.Name,
Year = l.Year,
Category = l.Genre,
PosterURL = l.PosterURL,
});

It looks like you're trying to join Movies to Categories by matching the Movie id to the Category id. Since the IDs are assigned independently, you will only get records back if by chance you have a Movie and a Category with the same ID.
Getting no records back would be why you never enter the foreach loop.
I see no relationships defined in your model, so DBMovies, DBCategories, and DBMoviesToCategories don't "know" they're related to each other.

Related

The multi-part identifier "t.subjectId" could not be bound. Entity Framework Core

I am facing problem, I write a query in Entity Framework Core using C#, but I am unable to get my final result. It will be great favour if someone help me.
I want to show students result of entry test, if subject result is not posted then it should show 0, means need to add left outer join. I write the below query, but when I execute it returns the error.
var result = _db.palSundayTests
.Where(w => w.testId == testId)
.Select(s => new
{
testId = s.testId,
testDate = s.testDate,
students = _db.palSundayTestStudents
.Where(w => w.testGroupId == s.testGroupId)
.Select(st => new
{
students = st,
results = (from tp in _db.palSubjInfo
join rs in _db.palStudentTestResult.Where(r => r.studentId == st.studentId)
on tp.subjectId equals rs.subjectId
into myres
from myview in myres.DefaultIfEmpty()
select new
{
myview.obtainedMarks
}).ToList()
}).FirstOrDefault(),
subjects = s.sundayTestTopic
});
When I run in POSTMAN, I get this error
The multi-part identifier "t.subjectId" could not be bound
The multi-part identifier "t.obtainedMarks" could not be bound
The multi-part identifier "t.studentId" could not be bound
The multi-part identifier "t.testId" could not be bound
You are mixing implicit joins with explicit joins. That is allowed, but you need to be aware of how to do that properly. may it help https://stackoverflow.com/a/7314936/11143288

LINQ troubles in C# using Entity Framework

I have a few tables and this is what I need to achieve.
This gets all the rows from one table
var FRA = from prod in _cctDBContext.Fra
where prod.ActTypeId == 1
From within that, I get all the rows where ActTypeID.
Then I need to query another table from with the ID's get from that
foreach (var item in FRA)
{
var FRSA = _cctDBContext.Frsa
.Select(p => new { p.Fraid, p.Frsa1,
p.Frsaid, p.CoreId,
p.RelToEstId, p.ScopingSrc,
p.Mandatory })
.Where(p => p.Fraid == item.Fraid)
.ToList();
}
I then need to push each one of these to Entity Framework. I usually do it this way:
foreach (var item in FRA)
{
var FinanicalReportingActivity = new FinancialReportingActivity { FinancialReportingActivityId = item.Fraid, ScopingSourceType = item.ScopingSrc, Name = item.Fra1, MandatoryIndicator = item.Mandatory, WorkEffortTypeId = 0 };
_clDBContext.FinancialReportingActivity.AddRange(FinanicalReportingActivity);
}
But because I have used 2 for each loops, I cannot get the variables to work because I cannot find a way to get local variables as the entity context.
Can anyone think of a better way to code this?
Thanks
It looks like you can do this as a single join:
var query =
from prod in _cctDBContext.Fra
where prod.ActTypeId == 1
join p in _cctDBContext.Frsa on prod.Fraid equals p.Fraid
select new
{
p.Fraid,
p.Frsa1,
p.Frsaid,
p.CoreId,
p.RelToEstId,
p.ScopingSrc,
p.Mandatory
};
It looks like you are loading data from one set of entities from one database and want to create matching similar entities in another database.
Navigation properties would help considerably here. Frsa appear to be a child collection under a Fra, so this could be (if not already) wired up as a collection within the Fra entity:
Then you only need to conduct a single query and have access to each Fra and it's associated Frsa details. In your case you look to be more interested in the associated FRSA details to populate this ReportingActivity:
var details = _cctDBContext.Fra
.Where(x => x.ActTypeId == 1)
.SelectMany(x => x.Frsa.Select(p => new
{
p.Fraid,
p.Frsa1,
p.Frsaid,
p.CoreId,
p.RelToEstId,
p.ScopingSrc,
p.Mandatory
}).ToList();
though if the relationship is bi-directional where a Fra contains Frsas, and a Frsa contains a reference back to the Fra, then this could be simplified to:
var details = _cctDBContext.Frsa
.Where(x => x.Fra.ActTypeId == 1)
.Select(p => new
{
p.Fraid,
p.Frsa1,
p.Frsaid,
p.CoreId,
p.RelToEstId,
p.ScopingSrc,
p.Mandatory
}).ToList();
Either of those should give you the details from the FRSA to populate your reporting entity.

EF6 IN clause on specific properties

Good morning,
I'm having trouble with a EF query. This is what i am trying to do.
First i am pulling a list of ID's like so (List of IDs are found in the included x.MappingAccts entity):
Entities.DB1.Mapping mapping = null;
using (var db = new Entities.DB1.DB1Conn())
{
mapping = db.Mappings.Where(x => x.Code == code).Include(x => x.MappingAccts).FirstOrDefault();
}
Later, i'm trying to do a query on a different DB against the list of Id's i pulled above (essentially a IN clause):
using (var db = new Entities.DB2.DB2Conn())
{
var accounts = db.Accounts.Where(mapping.MappingAccts.Any(y => y.Id == ?????????)).ToList();
}
As you can see i only got part way with this.
Basically what i need to do is query the Accounts table against it's ID column and pull all records that match mapping.MappingAccts.Id column.
Most of the examples i am finding explain nicely how to do this against a single dimension array but i'm looking to compare specific columns.
Any assist would be awesome.
Nugs
An IN clause is generated using a IEnumerable.Contains.
From the first DB1 context, materialize the list of Id's
var idList = mapping.MappingAccts.Select(m => m.Id).ToList();
Then in the second context query against the materialized list of id's
var accounts = db.Accounts
.Where(a => idList.Contains(a.Id))
.ToList();
The only problem you may have is with the amount of id's you are getting in the first list. You may hit a limit with the SQL query.
This will give the list of Accounts which have the Ids contained by MappingAccts
using (var db = new Entities.DB2.DB2Conn())
{
var accounts = db.Accounts.Where(s => mapping.MappingAccts.Any(y => y.Id == s.Id)).ToList();
}

C# List grouping and assigning a value

I have a list of Orders. This list contains multiple orders for the same item, see the table below.
I then want to assign each item that is the same (i.e. ABC) the same block ID. So ABC would have a block ID of 1 & each GHJ would have a block ID of 2 etc. What is the best way of doing this?
Currently I order the list by Order ID and then have a for loop and check if the current Order ID is equal to the next Order ID if so assign the two the same block ID. Is there a better way of doing this using linq or any other approach?
Order ID Block ID
ABC
ABC
ABC
GHJ
GHJ
GHJ
MNO
MNO
You can do this that way, it will assign same blockid for same orderid
var ordered = listOrder.GroupBy(x => x.OrderId).ToList();
for (int i = 0; i < ordered.Count(); i++)
{
ordered[i].ForEach(x=>x.BlockId=i+1);
}
it will group orders by orderid then assign each group next blockid. Note that it won't be done fully in linq, because linq is for querying not changing data.
Always depends of what better means for you in this context.
There are a bunch of possible solutions to this trivial problem.
On top of my head, I could think of:
var blockId = 1;
foreach(var grp in yourOrders.GroupBy(o => o.OrderId))
{
foreach(var order in grp)
{
order.BlockId = blockId;
}
blockId++;
}
or (be more "linqy"):
foreach(var t in yourOrders.GroupBy(o => o.OrderId).Zip(Enumerable.Range(1, Int32.MaxValue), (grp, bid) => new {grp, bid}))
{
foreach(var order in t.grp)
{
order.BlockId = t.bid;
}
}
or (can you still follow the code?):
var orders = yourOrders.GroupBy(o => o.OrderId)
.Zip(Enumerable.Range(1, Int16.MaxValue), (grp, id) => new {orders = grp, id})
.SelectMany(grp => grp.orders, (grp, order) => new {order, grp.id});
foreach(var item in orders)
{
item.order.BlockId = item.id;
}
or (probably the closest to a simple for loop):
Order prev = null;
blockId = 1;
foreach (var order in yourOrders.OrderBy(o => o.OrderId))
{
order.BlockId = (prev == null || prev.OrderId == order.OrderId) ?
blockId :
++blockId;
prev = order;
}
Linq? Yes.
Better than a simple loop? Uhmmmm....
Using Linq will not magically make your code better. Surely, it can make it often more declarative/readable/faster (in terms of lazy evaluation), but sure enough you can make otherwise fine imperative loops unreadable if you try to force the use of Linq just because Linq.
As a side note:
if you want to have feedback on working code, you can ask at codereview.stackexchange.com

Linq lambda expression many to many table select

I have three tables, which two of them are in many to many relationship.
Picture:
This is the data in middle mm table:
Edit:
Got until here, I get proper 4 rows back, but they are all the same result(I know I need 4 rows back, but there are different results)
return this._mediaBugEntityDB.LotteryOffers
.Find(lotteryOfferId).LotteryDrawDates
.Join(this._mediaBugEntityDB.Lotteries, ldd => ldd.LotteryId, lot => lot.Id, (ldd, lot) =>
new Lottery
{
Name = lot.Name,
CreatedBy = lot.CreatedBy,
ModifiedOn = lot.ModifiedOn
}).AsQueryable();
My question is, how can I retrieve all the Lotteries via many to many table WHERE I have LotteryOfferId given only?
What I want to achieve is to get data from lottery table by LotteryDrawDateId.
First I use LotteryOfferId to get DrawDates from middle table, and by middle table I get drawDateIds to use them in LotteryDrawDate table. From that table I need to retreive Lottey table by LotteryId in LotteryDrawDate table.
I gain this by normal SQL(LotteryOffersLotteryDrawDates is middle table in DB, not seen in model):
select
Name, Lotteries.CreatedBy, Lotteries.ModifiedOn, count(Lotteries.Id)
as TotalDrawDates from Lotteries join LotteryDrawDates on Lotteries.Id
= LotteryDrawDates.LotteryId join LotteryOffersLotteryDrawDates on LotteryDrawDates.Id =
LotteryOffersLotteryDrawDates.LotteryDrawDate_Id
where LotteryOffersLotteryDrawDates.LotteryOffer_Id = 19 group by
Name, Lotteries.CreatedBy, Lotteries.ModifiedOn
But Linq is different story :P
I would like to do this with lambda expressions.
Thanks
db.LotteryOffer.Where(lo => lo.Id == <lotteryOfferId>)
.SelectMany(lo => lo.LotteryDrawDates)
.Select( ldd => ldd.Lottery )
.GroupBy( l => new { l.Name, l.CreatedBy, l.ModifiedOn } )
.Select( g => new
{
g.Key.Name,
g.Key.CreatedBy,
g.Key.ModifiedOn,
TotalDrawDates = g.Count()
} );
You can do this:
var query = from lo in this._mediaBugEntityDB.LotteryOffers
where lo.lotteryOfferId == lotteryOfferId
from ld in lo.LotteryDrawDates
group ld by ld.Lottery into grp
select grp.Key;
I do this in query syntax, because (in my opinion) it is easier to see what happens. The main point is the grouping by Lottery, because you get a number of LotteryDrawDates any of which can have the same Lottery.
If you want to display the counts of LotteryDrawDates per Lottery it's better to take a different approach:
from lot in this._mediaBugEntityDB.Lotteries.Include(x => x.LotteryDrawDates)
where lot.LotteryDrawDates
.Any(ld => ld.LotteryDrawDates
.Any(lo => lo.lotteryOfferId == lotteryOfferId))
select lot
Now you get Lottery objects with their LotteryDrawDates collections loaded, so afterwards you can access lottery.LotteryDrawDates.Count() without lazy loading exceptions.

Categories

Resources