I have 2 tables as follows :
CatTable
CatCode
CatName
DogTable
DogCode
CatCode
NameCode
So I would like to write down a query where return me the list of all data present in the table CatTable
PLUS if in the Table DogTable the value in the field “CatCode” is the same of CatTable.CatCode and the field “NameCode” is Empty then should return a value "false" in the field “DogTable.CatCode”
Example
var query = from c in CatTable
from d in DogTable
where c.CatCode == d.CatCode
select new { c.CatCode, c.CatName, d.CatCode }
Do you have any suggestion about that?
a simple version is to use the Any to return the boolean of the logic you want on that last field
var query = CatTable.Select(ct => new
{
CatCode = ct.CatCode,
CatName = ct.CatName,
DogCatCode = !DogTable.Any(dt => dt.CatCode == ct.CatCode && dt.NameCode == "")
});
Related
I have created two tables: Claim and ClaimAttachments.
I'm trying to join them on ClaimID in order to get the filtered data from both the tables.
public ActionResult Index(int? search)
{
if (search!=null)
{
var Product = (from P in db.Claims
join C in db.ClaimAttachments on
P.ClaimID equals C.ClaimID
select new Claim
{
ClaimID = P.ClaimID,
ClaimBatchID = P.ClaimBatchID,
PatientControlNumber = P.PatientControlNumber,
PatientFirstName = P.PatientFirstName,
PatientLastName = P.PatientLastName,
ServiceFromDate = P.ServiceFromDate,
ServiceToDate = P.ServiceToDate,
});
return View(db.Claims.Where(x => x.ClaimID == search).ToList());
}
else
{
return View(db.Claims.ToList());
}
I'm able to get the searched result but from single table. The join is not working.
Currently you're only selecting from the Claims data:
return View(db.Claims.Where(x => x.ClaimID == search).ToList());
You have a join query just above that line of code:
var Product = (from P in db.Claims
join C in db.ClaimAttachments on
P.ClaimID equals C.ClaimID
select new Claim
{
ClaimID = P.ClaimID,
ClaimBatchID = P.ClaimBatchID,
PatientControlNumber = P.PatientControlNumber,
PatientFirstName = P.PatientFirstName,
PatientLastName = P.PatientLastName,
ServiceFromDate = P.ServiceFromDate,
ServiceToDate = P.ServiceToDate
});
But you don't do anything with the results of that query. It sounds like you meant to use the results of that query (which is in the Product variable, which incidentally should probably have a plural name since it's a collection) instead of just selecting from db.Claims. Something like this:
return View(Product.Where(x => x.ClaimID == search).ToList());
Note however that you're still only selecting data from one table. Though the join operation may alter the results of that selection. But the selection itself is here:
select new Claim
{
ClaimID = P.ClaimID,
ClaimBatchID = P.ClaimBatchID,
PatientControlNumber = P.PatientControlNumber,
PatientFirstName = P.PatientFirstName,
PatientLastName = P.PatientLastName,
ServiceFromDate = P.ServiceFromDate,
ServiceToDate = P.ServiceToDate
}
Notice how every value selected is from the P alias, which is defined here:
from P in db.Claims
So you're successfully joining the two tables, but only selecting data from one of the two tables. If you want to also select data from the other table then, well, you need to select data from the other table. For example, if there's a property on that table called SomeProperty that you want to select then you'd need to select it, and into an object which has that property.
For example, you might create a view model (let's call it ClaimViewModel as an example) which represents a combined record of the two tables, containing the properties you want from each. Then you'd select into that type:
select new ClaimViewModel
{
ClaimID = P.ClaimID,
ClaimBatchID = P.ClaimBatchID,
PatientControlNumber = P.PatientControlNumber,
PatientFirstName = P.PatientFirstName,
PatientLastName = P.PatientLastName,
ServiceFromDate = P.ServiceFromDate,
ServiceToDate = P.ServiceToDate,
SomeProperty = C.SomeProperty // <--- here
}
This would select the combined data into a list of ClaimViewModel objects, which you'd then filter based on your "search" and return to your view just like you do with the Claims objects now. And of course that view would need to be updated to expect a collection of ClaimViewModel objects instead of a collection of Claim objects.
I have linq where data in one of column may have spaces or special character between string, for example my survey, your's survey. I need to remove this so after filtering linq should return mysurvey and yourssurvey
column I am interested to remove spaces and special character is consultation = consultation.Name
I am using C# .net core and entity framework
var query = (from consultation in Context.Consultations
join survey in Context.Surveys on consultation.Id equals survey.ConsultationId into surveys
select new
{
consultationId = consultation.Id,
consultation = consultation.Name,
surveyId = surveys.FirstOrDefault() == null? null : surveys.Select(x=>x.Id),
survey = surveys.FirstOrDefault() == null ? null : surveys.Select(x => x.Name),
subject ="survey"
});
If you want to remove spaces & special characters in a string use like below:
consultation = Regex.Replace(consultation.Name, "[^0-9A-Za-z]+", "");
Using namespace
using System.Text.RegularExpressions;
Write an extension method like this
public static string StripSpacesAndSpecialCharacters(this string text)
{
var specChars = new string[] { "'", ";" }; // add more spec chars here
var procesesedString = text.Trim();
foreach (var spec in specChars)
{
procesesedString = procesesedString.Replace(spec, string.Empty);
}
return procesesedString;
}
then use it in your query like
var query = (from consultation in Context.Consultations
join survey in Context.Surveys on consultation.Id equals survey.ConsultationId into surveys
select new
{
consultationId = consultation.Id,
consultation = consultation.Name.StripSpacesAndSpecialCharacters(),
surveyId = surveys.FirstOrDefault() == null? null : surveys.Select(x=>x.Id),
survey = surveys.FirstOrDefault() == null ? null : surveys.Select(x => x.Name),
subject ="survey"
});
I want to select 2 or more fields like this: for example we have a list of some people and now they say find people who is male and live in New York
we have 2 fields in here "City" and "Sexual".
I can do it like this
private List<tblTest> GetAll(string city, string sexual)
{
var all = (from x in db.tblTest
where x.city == city && x.sexual == sexual
select x).ToList();
return all;
}
and this one is not helping:
private List<tblTest> GetAll(string city, string sexual)
{
var all = (from x in db.tblTest
where x.city == city || x.sexual == sexual
select x).ToList();
return all;
}
with "&&" I can do it but if I want to just select "City" it is not working, and I want to search like this for 14 fields and we want to search for some fields not all fields we have and we don't know which fields we want to search
What should I do?
The way I do is following:
private List<tblTest> GetAll(string city, string sexual)
{
var query = db.tblTest.AsQueryable();
if(!string.IsNullOrEmpty(city))
{
query = query.Where(x => x.city == city);
}
if(!string.IsNullOrEmpty(sexual ))
{
query = query.Where(x => x.sexual == sexual );
}
return all.ToList();
}
It is important to call AsQueryable otherwise it might be that, if you write IEnumerable<tblTest> query = ..., the result is queried more that 1 times.
I want to update one column in sql.in where condition two column names are there.
below is mu update query:
string sql = "UPDATE contact set ContactName=#ContactName where ContactID=#ContactId AND UserID=#Userid";
now I want to write using linq.How to write above query using linq.please help me.I tried
var updatequery = (from x in obj.Contacts where x.ContactID == ContactID select x).First();
updatequery.ContactName = ContactName;
obj.SubmitChanges();
but in the above query where condition having only one column name.I want to where condition having two column names.Thanks in advance.
You just have to use the conditional-AND operator &&:
var updateContacts = from x in obj.Contacts
where x.ContactID == ContactID && x.SecondColumn == SecondValue
select x;
// now use First or a loop if you expect multiple
foreach(var contact in updateContacts)
contact.ContactName = ContactName;
obj.SubmitChanges();
I don't know if this will help but you can try this as well.
var updatequery = obj.Contacts
.Where(x => x.ContactID == ContactID && x.SecondColumn == SecondValue)
.FirstOrDefault();
updatequery.ContactName = ContactName;
obj.SubmitChanges();
I have a table, lets say tblCar with all the related columns like Id, Make, Model, Color etc.
I have a search model for car containing two params Id and Model.
public class CarSearch
{
public int Id { get; set; }
public string Model { get; set; }
}
var carSearchObjets = new List<CarSearch>();
With list of primitive data (like Id list), to get cars with those Ids I could have done:
var idList = new List<int> { 1, 2, 3 };
var carsFromQuery = context.Cars.Where(x => idList.Contains(x.Id);
But if I have to fetch all the cars with Id and model from the list, how do I do it? Simple join cannot be done between in memory objects and tables.
I need something like,
from m in context.Cars
join n in carSearchObjets
on new { Id = n.Id, Model = n.Model } equals new { Id = m.Id, Model = m.Model }
select m;
This obviously won't work.
Please ignore any typos.And if you need more info or the question is not clear, let me know.
One (ugly-but-working) way to manage that is to use concatenation with a "never used" concat char.
I mean a char that should never appear in the datas. This is always dangerous, as... never is never sure, but you've got the idea.
For example, we'll say that our "never used" concat char will be ~
This is not good for perf, but at least working :
var carSearchObjectsConcatenated = carSearchObjets.Select(m => new { m.Id + "~" + m.Model});
then you can use Contains again (concatenating on the db too) : you'll need to use SqlFunctions.StringConvert if you wanna concatenate string and numbers on the db side.
var result = context.Cars.Where(m =>
carSearchObjectsConcatenated.Contains(SqlFunctions.StringConvert((double)m.Id) + "~" + m.Model);
EDIT
Another solution would be to use PredicateBuilder, as mentionned by Sorax, or to build your own Filter method if you don't want a third party lib (but PredicateBuilder is really fine).
Something like that in a static class :
public static IQueryable<Car> FilterCars(this IQueryable<Car> cars, IEnumerable<SearchCar> searchCars)
{
var parameter = Expression.Parameter(typeof (Car), "m");
var idExpression = Expression.Property(parameter, "Id");
var modelExpression = Expression.Property(parameter, "Model");
Expression body = null;
foreach (var search in searchCars)
{
var idConstant = Expression.Constant(search.Id);
var modelConstant = Expression.Constant(search.Model);
Expression innerExpression = Expression.AndAlso(Expression.Equal(idExpression, idConstant), Expression.Equal(modelExpression, modelConstant));
body = body == null
? innerExpression
: Expression.OrElse(body, innerExpression);
}
var lambda = Expression.Lambda<Func<Car, bool>>(body, new[] {parameter});
return cars.Where(lambda);
}
usage
var result = context.Cars.FilterCars(carSearchObjets);
this will generate an sql looking like
select ...
from Car
where
(Id = 1 And Model = "ax") or
(Id = 2 And Model = "az") or
(Id = 3 And Model = "ft")
'PredicateBuilder' might be helpful.
var predicate = PredicateBuilder.False<Car>();
carSearchObjects
.ForEach(a => predicate = predicate.Or(p => p.Id == a.Id && p.Model == a.Model));
var carsFromQuery = context.Cars.AsExpandable().Where(predicate);
Note the text in the link regarding EF:
If you're using Entity Framework, you'll need the complete LINQKit -
for the AsExpandable functionality. You can either reference
LINQKit.dll or copy LINQKit's source code into your application.
Old school solution..
//in case you have a
List<CarSearch> search_list; //already filled
List<Cars> cars_found = new List<Cars>();
foreach(CarSearch carSearch in search_list)
{
List<Cars> carsFromQuery = context.Cars.Where(x => x.Id == carSearch.Id && x.Model == carSearch.Model).ToList();
cars_found.AddRange(carsFromQuery);
}
Abd don't worry about the for loops.
I landed up passing in an xml list as a parameter to the sql query and joined to that:
var xml = new XElement("Cars", yourlist.Select(i => new XElement("Car", new XElement("Id", i.Id), new XElement("Model", i.Model))));
var results = Cars
.FromSql("SELECT cars.*"
+ "FROM #xml.nodes('/Cars/Car') Nodes(Node)"
+ "JOIN Cars cars on cars.Id = Nodes.Node.value('Id[1]', 'int') and cars.Model = Nodes.Node.value('Model[1]', 'varchar(100)')",
new SqlParameter("#xml", new SqlXml(xml.CreateReader())));
For entity-framework-core users I created a nuget package extension:
EntityFrameworkCore.SqlServer.Extensions.Contains