SQL TO linq in c# - c#

This code is from my sql query
SELECT Branchname
FROM Branch
WHERE NOT EXISTS (SELECT Branchname FROM vBranching
WHERE Branch.Branchname = vBranching.Branchname AND UserName = 'xCuttiepies');
iwant to execute it into linq c# web api
Its look like this
var Branch = _dbcontext.Branches.Select(c => c.Branchname).ToList();
var vBranching = _dbcontext.VBranchings.Select(a => a.BranchName).ToList();
var ass = Branch.Where(!Branch.Exists(Branch == vBranching));
return Ok(vBranching);
In Branch == vBranching it says cannot convert from bool to System.Predicate<string>
I want to fetch the data that not exists on that different tables.

You souldn't be using ToList except right at the end, and your lambda syntax is off, and the equivalent of EXISTS is Any. You are also returning the wrong value.
var Branches =
_dbcontext.Branches
.Where(b => !_dbcontext.VBranchings.Any(vb =>
vb.BranchName == b.BranchName && vb.UserName == "xCuttiepies"))
.Select(c => c.Branchname)
.ToList();
return Ok(Branches);

Related

Unable to convert SQL query to linq query which contains subquery and need to handle two tables

We are converting a SQL query to a linq query, this conversion is involving two tables as follows:
select *
from Tbl_Vulpith_Registration
where Profile_Pic is not null
and MemId IN (select MemId from Tbl_List_Services)
Tbl_Vulpith_Registration and Tbl_List_Services are the two tables involved.
memId is the common column in the both the tables.
This is what we tried to convert the above SQL query to linq:
var reglist = objentity.Tbl_Vulpith_Registration.Select(a => a).Where(a => a.Profile_Pic != null);
var listmemsmemIds = objentity.Tbl_List_Services.Select(b => b.MemId).ToList();
var finalist = reglist.Select(b => b).Where(c => c.MemId.Contains(listmemsmemIds));
I guess MemId is a numeric type, if so, then you are using Contains wrong, correct your last statement to:
var finalist = reglist.Select(b => b).Where(c => listmemsmemIds.Contains(c.MemId));
Or even better, use the query syntax, it will get your result in one statement:
var finalist = (from a in objentity.Tbl_Vulpith_Registration
where a.Profile_Pic != null && (from b in objentity.Tbl_List_Services select b.MemId).Contains(a.MemId)
select a).ToList();
(from r in Tbl_Vulpith_Registration.Where(r => r.Profile_Pic != null)
from s in Tbl_List_Services.Where(s => s.MemId == r.MemId)
select r).ToList();
I believe you could also use this approach where you join these tables on the common MemId column.

selecting properties from other table with Lambda expression

I am less experienced with Lambda expression for .NET and trying to get data from SQL using lambda expression. With below query, I am able to get data back, but do not want to use include to get all properties from other tables.
public IEnumerable<ResourceGroup> GetAllServersByApplication(string application_name, string environment_name, string status)
{
var query = _context.ResourceGroup
.Include(a => a.Application)
.Include(t => t.Type)
.Include(e => e.ServersGroup).ThenInclude(e => e.Environment)
.Include(s => s.ServersGroup).ThenInclude(s => s.Server)
.Include(s => s.ServersGroup).ThenInclude(s => s.Server).ThenInclude(s => s.Status)
.Where(a => a.Application.Name == application_name && a.ServersGroup.Any(s => s.Environment.Name == environment_name && s.Server.Status.Name == status))
.ToList();
return query;
}
Lets take an example of below include statement.
.Include(s => s.ServersGroup).ThenInclude(s => s.Server)
From s.Server, I only want to select Id,ServerName,Status, and IPAddress. These are the properties from Servers class that I created as a model.
What is the easy way to exclude all the includes and only show properties that I am interested in?
Here are my tables and its properties:
Status table:
Id, Name
Application table:
Id, Name
Servers table:
Id, ServerName, Status
Environments table:
Id, Name
ResourceGroup table:
Id, Name, Application_Id, Environment_Id
ServersResourceGroup table:
Id, Server_Id, Resource_Id
UPDATE 1:
var query = _context.ResourceGroup
.SelectMany(rg => rg.ServersGroup
.Select(sg => new
{
ResourceName = rg.Name,
ApplicationName = rg.Application.Name,
ServerName = sg.Server.ServerName,
EnvironmentName = sg.Environment.Name,
Status = sg.Server.Status.Name
})).Where(a => a.ApplicationName == application_name && a.EnvironmentName == environment_name && a.Status == status).ToList();
return query;
And error from red line on query variable:
UPDATE 2:
Here is the query syntax:
var query = from rg in _context.ResourceGroup
let app = rg.Application
from sg in rg.ServersGroup
let env = sg.Environment
let srv = sg.Server
let stat = srv.Status
where app.Name == application_name
&& rg.ServersGroup.Any(s => s.Environment.Name == environment_name
&& s.Server.Status.Name == status)
select new
{
ResourceGroupName = rg.Name,
ApplicationName = app.Name,
ServerName = srv.ServerName,
Alias = srv.Alias,
IPAddress = srv.IPAddress,
Type = rg.Type.Name,
Status = stat.Name
};
return query;
Here is the red line error I get in query variable:
Your help is really appreciated. :)
Thanks,
Ray
With lambda expressions, you can use SelectMany to flatten 1-n associations into a 1 dimensional list (i.e. parent and child properties side-by-side). In your case, judging from the Where clause, I think only ResourceGroup - ServerGroup is 1 - n, so it should be something like:
var query = _context.ResourceGroup
.SelectMany
(
rg => rg.ServersGroup
.Select(sg => new
{
ResourceGroup = rg.Name,
Application = rg.Application.Name,
Server = sg.Server.ServerName,
// etc.
})
)
Of course it's good to know how to use lambda expressions, but there's really no point in using them when query syntax makes for much better comprehensible code.
The equivalent in query syntax is:
var query = from rg in _context.ResourceGroup
let app = rg.Application
from sg in rg.ServersGroup
let env = sg.Environment
let srv = sg.Server
let stat = srv.Status
where app.Name == application_name
&& sg.ServersGroup.Any(s => s.Environment.Name == environment_name
&& s.Server.Status.Name == status)
select new
{
ResourceGroup = rg.Name,
Application = app.Name,
Server = srv.ServerName,
// etc. use any property from rg, app, sg, srv, stat
};
As you see -
n - 1 associations are represented by a let statement (which really only helps here to shorten the references in the select)
1-n associations are represented by the from ... from syntax, which is query syntax for SelectMany.
I didn't change the Where clause in the query syntax. Maybe you can use ...
where app.Name == application_name
&& env.Name == environment_name
&& stat.Name == status)
... but note that this is different. The original where returns all ResourceGroup having at least one ServerGroup meeting the condition (and maybe other groups with different environments and statuses). The other where only returns data with environments and statuses equal to the search parameters.
Don't Include all the related tables, but Select all the fields you need. You might find it easier to make a new class to hold the data.
Sorry if I can't make a real query statement here, but your question doens't specify the fields you need.

What is lambda equivalent an SQL "in" statement?

I can't figure out a lambda equivalent of this sql statement:
select * from Document
where Document.OrginalDocumentNumber
in (select documentAccess.DocumentId from documentAccess where userId='1')
The problem is that Document & documentaccess tables have no relation to each other.
Any help would be so much appreciated.
Replace IN with EXISTS and you get following:
from d in dbContext.Documents
where dbContext.documentAccesses.Any(
x=>x.DocumentId == d.OrginalDocumentNumber && x.userId == '1' )
select d
Normally, if you have sensible navigation properties, you can avoid join or sub-queries directly:
var documents = from documentAccess in contex.DocumentAccesses
where documentAccess.UserId == 1
select documentAccess.Document;
You may want to use .Distinct() on the results, depending on your data.
Similarly:
var documents = contex.DocumentAccesses
.Where(access => access.UserId == 1)
.Select(access => access.Document);
And even better, if you already have a User in context:
var documents = currentUser.DocumentAccesses.Select(access => access.Document);

Some part of your SQL statement is nested too deeply c# EF 5

I’m getting the following exception from EF 5:
Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.
Here is my Query:
String username = “test”;
IEnumerable<Int32> roles;
IEnumerable<Int32> applications;
cnx.Users.Where ( it =>
( userName != null ? it.name = = userName : true ) &&
( !roles.Any () || roles.Contains ( it.role_id ) ) &&
( ! applications.Any () || applications.Contains ( it.application_id ) ) )
.Count ();
Users is a simple table.
Roles and applications are both typeof IEnumerable and can be empty.
How can I change my query, that it will work in EF 5 (.Net 4.0)?
For me it looks like userName, roles and applications are parameters to the query, i.e. the data comes from your application and not from the database. In that case, I would write the query like this:
IQueryable<User> query = cnt.Users;
if(userName != null)
query = query.Where(x => x.name == userName)
if(roles.Any())
query = query.Where(x => roles.Contains(x.role_id));
if(applications.Any())
query = query.Where(x => applications.Contains(x.application_id))
var result = query.Count();
This is a lot more readable and doesn't include unnecessary clutter into the resulting query.
Please note that roles and applications must not represent the unexecuted result of another query.
With "unexecuted result", I mean the following:
IEnumerable<Role> roles = context.Roles.Where(x => x = y);
Another solution, are iterate over the records getting the another ones and aggregate to an final list.
It's not fastest, not beauty, but will solve.

Building a custom|progressive query in LINQ?

I have a page with five text boxes, each one representing a field in my database table and a search button:
If I were using SQL I could build my SQL statement depending on which fields have data in them.
However, I want to use LINQ, and I'm at a loss as to how to accomplish this. For instance, take a look at the query below:
var db = new BookDBDataContext();
var q =
from a in db.Books
where a.Title.Contains(txtBookTitle) &&
a.Author.Contains(txtAuthor) &&
a.Publisher.Contains(txtPublisher)
select a.ID;
The query above will return data where all the fields match data in the table. But, what if the user didn't enter an Author in the txtAuthor field? If I were building this as a query string, I could check each field for data and add it to the query string. Since this is LINQ, I can't dynamically change the search criteria, it seems.
Any advice would be greatly appreciated!
var db = new BookDBDataContext();
var q = (from a in db.Books
where a.Title.Contains(txtBookTitle));
if(!String.IsNullOrEmpty(txtAuthor))
{
q = q.Where(a => a.Author.Contains(txtAuthor));
}
if(!String.IsNullOrEmpty(txtAuthor))
{
q = q.Where(a => a.Publisher.Contains(txtPublisher));
}
var id = q.Select(a => a.ID);
from a in db.Books
where (string.isNullorWhiteSpace(search) || a.Title.Contains(search)) &&
(string.isNullorWhiteSpace(txtAuthor) || a.Author.Contains(txtAuthor) ) &&
(string.isNullorWhiteSpace(txtPublisher) || a.Publisher.Contains(txtPublisher))
select a.ID;

Categories

Resources