Selecting multiple from LINQ query - asp.net-mvc

I use this little piece of code to get the IDs I need, and put them in an array
var userids = from a in db.Person
select a.idlist;
string[] idarray = userids.FirstOrDefault().ToString().Split(';');
How can I use this array of ids to select the matching rows in another query like this
[HttpGet]
public ActionResult GetStuff()
{
var Item = from a in db.Table
where a.id == idarray[0]
and where a.id == idarray[1]
and where a.id == idarray[2]
etc...
select new
{
a.itemid,
a.Element
};
return Json(Item, JsonRequestBehavior.AllowGet);
}

Try something like this:
var Item = from a in db.Table
where idarray.Contains(a.id)
select new
{
a.itemid,
a.Element
};

var Item = from a in db.Table
where idarray.Contains(a.id)
select new
{
a.itemid,
a.Element
}.ToArray();

Don't you want to use Extension Method Lambda syntax? I is same Linq, but just has more code-like view:
var Item = db.Table.Where(x => x.Contains(a.id))
.Select(x => new
{
a.itemid,
a.Element
}).ToArray();

Here's what I usually do.
Get the IDs you need:
var ids = something.Where(s => s.SomeCondition).Select(s => s.Id);
Now Lets get the data based on the Ids:
var response = anothertable.Where(a => ids.Contains(a.Id);
You then can make it a list, array, or whatever you want to do with it. It will go through all the records in anothertable and find the records where the a.Id matches any of the ids.

Related

How to create linq to get all records group by columnname

I have written below code but I am getting only one record of each ExchangeDataId.
Please help to get all the data which is groupby ExchangeDataId.
var Report = ExchangeLeads.GroupBy(c => new
{
c.ExchangeDataId
}).SelectMany(grouping=>grouping.Take(1)).ToList();
ExchangeLeads
.GroupBy(c => c.ExchangeDataId)
.Select(group=> new { Id = group.Key, Items = group.ToList() })
.ToList()
You can try the following,
var result = ExchangeLeads.ToLookup(x => x.ExchangeDataId).Select(x => new { Id = x.Key, ExchangeLeads = x.ToList() }).ToList();
Lookup is more efficient than GroupBy here.

Entity Framework - How can I check whether an object is under another object's Hierarchy?

I have an table called Contents. There's one to many relationship on Contents, so each content can have a parent and children. I'm using EF Code First, so I have an entity Content which has Id, ParentId, Parent and Children properties.
Now, I'm building an ajax based tree of Contents. I have a simple action that returns a JSON of one level of Contents, based on parentId:
public JsonResult GetContents(int? parentId = null)
{
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
});
}
The next thing I want to do is to automatically select some value. The problem is that the value can be deep inside the hierarchy of the tree, so for each content I'll need to know whether or not the selected value is a child or grandchild and so forth, of it.
public JsonResult GetContents(int? parentId = null, int selectedValue)
{
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy: // How can I efficiently implement this?
});
}
It's easy to implement with a lot of queries, but I'm trying to make things as efficient as possible, and EF doesn't provide any Recursive methods as far as I know, so I really have no clue where to start.
You could first build a list of all the ParentIds from the selected value. Depending on the size of your Contents table, you could first load the data, then loop through without making extra queries to the database.
db.Contents.Load();
var selectedItem = db.Contents.Find(selectedValue);
var parents = new List<int>();
while (selectedItem.ParentId != null)
{
parents.Add(selectedItem.ParentId.Value);
selectedItem = selectedItem.Parent;
}
Alternatively, you could use CTE (Common Table Expression).
var parents = db.Database.SqlQuery<int>("sql statement");
Once you have a list of parents, you can use Contains.
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy = p.ParentId.HasValue && parents.Contains(p.ParentId.Value)
});
UPDATE: CTE Example
You'd probably want to use a stored procedure, but this code should work.
var sql = #"with CTE as
(
select ParentId
from Contents
where Id = {0}
union all
select Contents.ParentId
from Contents
inner join CTE on Contents.Id = CTE.ParentId
)
select *
from CTE
where ParentId is not null";
var parents = db.Database.SqlQuery<int>(string.Format(sql, selectedItem)).ToList();

Joining of two queries and returning in list format

I am developing a MVC application.
I am using the two queries to fetch the record, and I want to get the common records from these queries .
I want to return the data set in list
Like this
return Json(poList, JsonRequestBehavior.AllowGet);
My two queries are..
var poList = (from po in db.PurchaseOrders
where po.CompanyId == companyId && po.PartyId == partyId && (po.IsDeleted == false || po.IsDeleted == null)
select po into newPO
select new
{
Name = newPO.PONo,
Id = newPO.Id
});
//.ToList().OrderBy(e => e.Name);
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new { Name = po.PONo, Id = po.Id }));
var finalPO = from PO in poList.ToList().Union(poList2).ToList() select PO);
The reason you can't union them is that the two lists return different objects.
The first list returns an anonymous type with members Name and Id. If, instead, you just wanted to return the purchase orders in query one, then you could simply use the following:
var poList = (
from po in db.PurchaseOrders
where po.CompanyId == companyId &&
po.PartyId == partyId &&
(po.IsDeleted == false || po.IsDeleted == null)
select po
);
You may need to append .ToList() to the query above in order to use the Union(...) method. Then, you should be able to union the two sequences together (assuming poList2 is also a sequence of db.PurhaseOrders objects.
Conversely, instead of changing query for poList above, you could change the query behind poList2 to the following to achieve the same effect, but different results:
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new { Name = po.PONo, Id = po.Id }));
Personally, I think the first one is more clear (unless there are many fields on the PO object and you only need the two as shown).
UPDATE: I see the original post was edited so that both queries now return the same object (or shape of object). However, the poster is still trying to combine the results incorrectly. The poster is using yet another LINQ query in an attempt to use the Union(...) method. This is completely unnecessary. Might as well write out the code for him/her:
var finalPO = poList.Union(poList2).ToList(); // ToList() only necessary if you need a list back
That should do it.
Really, the two books I mentioned in my comments below will get you a long way in understanding .NET and LINQ: APress - Pro C# and the .NET Framework 4.0; O'Reilly - C# 5 in a Nutshell. There are also many books on LINQ alone--but without a solid grasp of .NET (and C#, F#, or VB), you can't hope to understand or use LINQ.
I dont not think you need the ToList() in the intermediate results, just use the union and do the ToList in the final result, like:
var finalPO = poList.Union(poList2).ToList()
First, create a ViewModel like this:
public class PurchaseOrderViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Then, use it in your code like this:
var poList1 = (from po in db.PurchaseOrders
where po.CompanyId == companyId && po.PartyId == partyId
&& (po.IsDeleted == false || po.IsDeleted == null)
select po into newPO
select new PurchaseOrderViewModel
{
Name = newPO.PONo,
Id = newPO.Id
}).ToList();
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new PurchaseOrderViewModel
{
Name = po.PONo,
Id = po.Id
})).ToList();
var finalList = poList1.Union(poList2);

Select object and modify field linq

I have the following Linq Query :
var list = (from user in serviceu.Repository.FindFind(<<filtering nonsense>>)
from profile in serviceP.Repository.GetQuery().Where(p => p.userID == user.userID).DefaultIfEmpty()
select user ).ToList();
Basically i have to add ProfileId to my user entity. Doing this join only lets me select the user element but i want to change the value of user.profileID=profile.profileID ( I have extended the object so it has that field ). How can this be done the fastest way?
I have solved it temporarily by doing this :
var list = (from user in serviceu.Repository.Find(<<filtering nonsense>>)
from profile in serviceP.Repository.GetQuery().Where(p => p.userID == user.userID).DefaultIfEmpty()
select new { user, profile.ProfileID }).ToList();
list.ForEach(el =>
{
el.user.ProfileID = el.ProfileID.ToString();
});
return list.Select(x => x.user).ToList();
Is this the best ( fastest/elegant way )? Can it be done differently?
Instead of ForEach and return try:
return list.Select(c => {c.user.ProfileID = c.ProfileID.ToString(); return c;}).ToList();

With Linqtosql, How to get a collection of Users based on an array of UserID's

Using linqtosql, how would I get a colleciton of User objects, if I have an array of UserID's that I want to fetch?
You can use Contains to check if each UserID is in the array that you have.
int[] userIDs = ...
var users = db.Users.Where( u => userIDs.Contains( u.UserID ) );
If you want to avoid a SET operation and user chained ORs instead, you can use the PredicateBuilder to help you with that.
It goes something like this:
var userIDs = new[] { 1, 2, 3, 4, 5 };
// build multiple OR expressions
var filter = PredicateBuilder.False<User>();
foreach (var id in userIDs) {
filter = filter.Or(x => x.UserID == id);
}
// fetch data
using (var db = new TheDataContext()) {
var users = db.Users.Where(filter);
// wham! - we have users now.
}
Take a look at the blog post to understand how it works. This basically creates a long chaining ORs for each user id in the list before passing it to a WHERE clauses.
Try this:
using(var db=new MyDataContext())
{
var users=db.Users.Where(u=>userIds.Contains(u.Id));
}

Resources