Linq List Contains Method - c#

Im newbie to linq and im using linq query to retrieve data from the table.My idea is to list all the cashsafes corresponding to a particular user and show it in dropdownlist.
The table structure is shown below
Table 1
cashsafeid cashsafename
1 cashsafe1
2 cashsafe2
3 cashsafe3
Table 2
Id UserId Cashsafeid
1 100 1,2,3
2 101 1,3
I've to get the cashsafename of a particular user say 100.How can i achieve it
The below code is the one i've tried but am stuck
List<Cashsafe> cashsafes=(from c in db.Table 1
where c.CashsafeId contains() )--Cannot go further

You store User's Cachsafeid column in very inefficient way - it doesn't allow to generate efficient SQL for LINQ provider. So the following solution has bad performance - if you care about that - change your table structure.
var user = db.Table2.Single(u => u.UserId == 100);
var cachfeIds = user.Cashsafeid.Split(',').Select(int.Parse).ToArray();
var cachefes = db.Table1.Where(c => cachfeIds.Contains(c.Id)).ToList();
Basically you need to join to tables, but foreign key is "virtual" - it is only in your mind. To retrieve foreign key values we must split the Cachsafeid column's value of every user to retrieve linked cachefes. And only then retrieve the cachefes with separate request (I think LINQ will retrieve all values from table and the execute Where part in C# code).

if you have no idea of join you can use
int x = 0;
List<int> Users = db.table2.FirstOrDefault(m => m.UserId == 100).Cashsafeid.Split(',').ToList().Where(str => int.TryParse(str, out x)).Select(str => x).ToList(); ;
var content = db.table1.Where(m => Users.Contains(m.cashsafeid)).ToList();

Related

Convert sql query to lambda expression for table with foreign keys

I have 2 tables. One is a user table that holds userid and userSelection(foreign key to another table) both are primary keys so multiple rows for a user.
The 2nd table holds columns with it's primary id being userSelection.
I want to retrieve all the userSelection rows that a userId has from the 2nd table. I want to use linq lambda expressions too.
I have it working in sql jsut can't convert it for use in c#.
Select * From column
where colID in (
select colId from users
where userID = 'someUser')
Thanks
Assuming you're using Entity Framework, what you're really looking for is an inner join. it would look something like this:
from c in context.Column
join u in context.Users on c.ColId equals u.ColId
where u.UserId = 'SomeUser'
select c;
as a lambda that is something like (syntax might be lacking something) (no where clause here, but easily added)
context.Column.Join( context.Users, u => u.ColId, c => c.ColId).Select
Change this code to two parts
Select * From column
where colID in (
select colId from users
where userID = 'someUser')
First part to get colId list:
var colIds = context.users.Where(x=>x.userID == "someUser").Select(x=>x.colId).ToList();
Second part to get the result use Where and List.Contains
// IQueryable result
var result = context.column.Where(x=>colIds.Contains(x.colID));
You can use it inline, but I recommend it to be two parts.

Querying against multiple columns in Entity Framework 6

I'm trying to execute a query against multiple columns in EF 6 (using C# WPF on VS 2013), I need to select all fields of some columns. I really don't know much but I already tried to do it with Linq and it doesn't seem to have that functionality, so I went with <context>.Database.SqlQuery<string>(query), but it's unclear to me how should I handle what it returns. The query is something simple like "SELECT column1,column2 FROM table".
Is it possible to do it with Linq? How? And for the SqlQuery() case, How should I handle it's result, being most of its columns are in string format?
#MiloGP yes you can do it with using Lambda Expression with LINQ
Here a example:
I have 5 columns in table employee(emp_id,emp_name,emp_dob,emp_address,emp_reference)
and My DBContext name : EmployeeEntities;
I trying to get emp_name and emp_address
List<employee> = EmployeeEntities.employees.select( x => new { x.emp_name, x.emp_address }).ToList();
if you need to get value of someone, As a example emp_id == 13458
List<employee> = EmployeeEntities.employees.Select( x => new { x.emp_name, x.emp_address }).Where( y => y.emp_id == 13458).ToList();

LINQ - Not returning the same value as SQL Server

I have a really weird issue.
I have this query:
var systemAppEntityViewModelFieldCustom_SecurityByUserList = (from t in coreEntityModel.SystemAppEntityViewModelFieldCustom_SecurityByUser
where (t.SystemAppUserID == CurrentSystemAppUser.SystemAppUserID)
&& (t.SystemCultureID == CurrentSystemAppUser.SystemCultureID)
select t).ToList();
Producing these values for the field "CustomFilterID":
As you can see, "CustomFilterID" = 1 for all 4 items, but when i check SQLProfiler and a run the result query in SQLServer, i get this:
A variation of "CustomFilterID" = 1 AND 2.
Any idea why LINQ will produce all 4 items with a "CustomFilterID" = 1?
Found the issue. My View was not selecting the PK column of the table and by adding the PK column of the table to the select list of the View, it produced the correct results.

Linq-To-Entities 'Contains' clause 1-many relationship

Consider a (simplified) table structure like this:
[USERS]
EMPID
NAME
[APPOINTMENTS]
(FK_APPT_USER) EMPID
APPTTYPEID
COMPLETE
Each user can have 0..* appointments, each of which can be one of many APPTYPEID's, and can either be complete or not complete.
I want to filter the result set of a IQueryable[USER] query such that it only includes USERS who have an appt of some typeID (say 1) and where the COMPLETE field is in a list of values. I'm doing this as part of a gridview filter that allows users to select either to show only completed or not completed users for particular appointment types.
List<string> vals = new List<string> {"Y","N"}
//maybe the user has only selected Y so the above list only contains 1 element
var qry = ctx.USER.Where(x=> vals.Contains( ? ));
//bind etc
This is really easy to do if the values I'm comparing against the list are in a 1-1 relationship with the USER object, for example:
var qry = ctx.USER.Where(x=> vals.Contains(x.NAME));
But I don't understand how to do it with a 1-many relationship like with my appointments table, it's getting me all brain-tied trying to conceptualize the entity sql for it. Can anybody explain how to do this?
qry = ctx.USER.Where(u => u.APPOINTMENTS
.Where(a => a.APPTYPEID == 1)
.Any(a => vals.Contains(a.COMPLETE)));
UPDATE (added returning those users, which do not have appointments at all)
qry = ctx.USER.Where(u =>
!u.APPOINTMENTS.Any() ||
u.APPOINTMENTS.Any(a => a.APPTYPEID == 1 && vals.Contains(a.COMPLETE)));

How to select only rows that have a unique value in one column?

Consider this example data:
field1 field2
1 100
2 100
3 101
4 102
5 102
6 103
I want to select only the records where the value in field2 occurs only once. An example of the desired return data from the above would be:
field1 field2
3 101
6 103
How would this be done with LINQ to SQL?
--- EDIT -------
Hello all, thank you for your responses. I purposely supplied simplified data to get right to the root of my question. I think all these answers return the desired results based on my example data and I will be marking them all answers as such.
however in my real data scenario, using what I've learned from your responses, I have something like this:
var RefinedSource = from a in dSource
group a by a.AssetID into g
where g.Count() == 1
select new
{
AssetID = g.Key,
AssetType = g.Min(a => a.AssetType),
IPInfo = AppUtility.GetIPInfo(g.Key),
Hostname = AppUtility.GetServerName(g.Key),
DeviceID = g.Min(a => a.DeviceID).ToString(),
Environment = AppUtility.GetSolutionAndEnvironmentNames(g.Key),
Manufacturer = g.Min(a => a.Manufacturer),
MakeModel = g.Min(a => a.MakeModel),
Location = g.Min(a => a.Location),
count = g.Count()
};
So I'm concerned about all the .min() calls... I've deduced these are necessary because of the grouping? could someone explain why these are needed? In the case of my simple example I don't see them being an issue, but with my real data there a multiple calls to min() just to be able to include all the field data I need... which doesn't seem good.
The grouping allows me to test the condition I need (that count to identify duplicate values) but how do I more directly use a condition like this but just access my real underlying data rows directly?
for example, looking at the example I just supplied above, I would like to be able to just use a.FieldName from the original "from a in dSource" part, but you can't access that after you have introduced "group by"?
again, thanks for the info, I will be marking as answers, however if anyone could explain the need for all the calls to min() (or max, or whatever) I would appreciate it, also, seeing what it looks like with my real data, is this still the way I should go?
from r in tables
group r.field2 by r.field1 into grp
where grp.Count() == 1
select new {grp.First(), grp.Key}
I'd double check that this does one SQL call. It should, and if so I'd keep it as here because First is a very commonly used Linq method, and when there's a few dozen equally good things to use in a given case one should favour the familiar. If it did cause more than one SQL call (again, I'd be surprised), then try Max() or Min() instead of First().
Here is how it would be done in SQL (sometimes it is faster to use SQL):
SELECT max(field1), field2
FROM table
GROUP BY field2
HAVING count(field2) = 1
Example using window function in sql server
(note, can't test right now the OVER clause might need to be in the where):
SELECT COUNT() OVER(PARTITION BY field2) AS [field2Count], *
FROM table
WHERE [field2Count] = 1
With LINQ you can do simply :
var groups = list.GroupBy(r => r.Value).Where(grp => grp.Count() == 1);
foreach(var gr in groups){
var field1 = gr.Key; // KEY: is your FIELD1
var field2 = gr.Value; // VALUE: is your FIELD2
}

Categories