best way to select...where in using linq - c#

There are three tables in the database that are relevant. Advocate, Vendor, and Advocate_Vendor.
The Advocate_Vendor table being the many to many link, has a vendorId and an advocateId.
My end goal is to get back a List<Advocate> object...a collection of advocates that belong to one Vendor. I wrote this:
var list = new List<Advocate>();
foreach (var vendorAdvocates in db.Advocate_Vendors)
{
if (vendorAdvocates.VendorId == vendorId)
{
list.Add(db.Advocates.SingleOrDefault(a => a.AdvocateId == vendorAdvocates.AdvocateId));
}
}
And then this:
var list = (from vendorAdvocates in db.Advocate_Vendors
where vendorAdvocates.VendorId == vendorId
select db.Advocates.SingleOrDefault(a =>
a.AdvocateId == vendorAdvocates.AdvocateId)).ToList();
Is this the best way? Seems wrong, like maybe there could be a more streamlined way to do this using a 'contains' keyword or something that looks a bit more readable...get all the vendor's advocates
thanks

Using a join between Advocate_Vendors and Advocates would be the right way of doing it.
var list = (from vendorAdvocates in db.Advocate_Vendors
join advocates in db.Advocates
on vendorAdvocates.AdvocateId equals advocates.AdvocateId
where vendorAdvocates.VendorId == vendorId
select advocates).ToList();

var list = (from vendorAdvocates in db.Advocate_Vendors
from advocate in db.Advocates
where vendorAdvocates.VendorId == vendorId &&
vendorAdvocates.AdvocateId = advocate.Id
select advocate)
.ToList();

If you set up your foreign keys and navigation properties properly, it should be possible to write this way, or something like it:
var list = (from vendorAdvocates in db.Advocate_Vendors
where vendorAdvocates.VendorId == vendorId
select db.Advocate).ToList();

Related

Linq to Sql - How to get data from second level table

I'm newbie to linq to sql, just trying to understand what type of queries I can handle with linq.
Here is my database scheme,
I want to get all customers of a specific user and this is what I've done,
var userId = 4;
var companies = from c in db.Company
where c.UserId == userId
select c.Id;
var costumers = from c in db.Customers
where companies.Contains(c.CompanyId)
select c;
I'm just wondering whether it's a nice approach and is there any better method to handle this type of queries?
Use can also get customers by this way also:
var result = db.Customers.Join(
db.Company, customer => customer.CompanyId, comp => comp.Id, (customer, comp)
=> new { customer, comp }).Where(#t => #t.comp.UserId == 4)
.Select(#t => #t.customer);
You can also keep it simple like this.
select * from db.Customers Cus
inner join db.company Com on Com.Id = Cus.CompanyId
where Com.UserId= userId
Contains is the equivalent of IN in SQL and your Linq statement will be translated to a SQL statement. So I can't really see another way that will give you better performance with Linq. If you want to use less code you can maybe try the following instead:
var companies = db.Companies.Where(x=> x.UserId == userid).Select(x=>x.Id);
var customers = db.Customers.Where(x=> companies.Contains(x.CompanyId));

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;

LINQ: Problem using DB with relations

I don't know how can I return posts to my view where their tags are equal to those who are passed to controller action.
I think there is some clever and easy way of doing this but I am very new to LINQ and SQL.
Code
// id = tag name, not it's id
public ActionResult Tag(string id)
{
// I get all the PostTags where PostTags.Tag.Name = id
var postTags = _db.PostTags.Where(x => x.Tag.Name == id);
// And what I do now?
}
Using joins in relational data is easier to grasp as a novice using query syntax instead of extension methods. The following is possible with extension methods (like .Join(...), etc), but this is closer to the SQL you might already be used to.
var postTags = from t in _db.Tags
join pt in _db.PostTags on t.ID equals pt.TagID
join p in _db.Posts on pt.PostID equals p.ID
where t.Name == id
select p;
Well to select them you could do something similar to..
var posts = _db.Posts.Where(post => post.PostTags.Any(postTag => postTag.Tag.Name == id));
This will just select all Posts where any of the related PostTags has a Tag with the name passed.

Nested select top 1 in Linq

having some problems figuring this one out.
select *,(select top 1 chicken_nr from chicken_photo where chicken = code order by [sort]) as Photo from Chicken
Code is a column in Table Chicken
Basically getting the cover photo for this chicken.
To make it clearer, I want it to return multiple rows from table Chicken. But only a single entry from chicken_photo.
var q = from chicken in data.chickens
join photos in data.chicken_photos
on chicken.Code equals photos.chicken
where chicken.Lang==lang && chicken.photographer_nr == nr
group chicken by new {chicken.photographer,photos.Photograph_Nr,chicken.Title,chicken.Code}
This can indeed be done such that it results in only one SQL query underneath.
If you perform the subselect as you have written against Entity Framework, then the Linq query will become a single SQL query.
var q = from chicken in data.chickens
where chicken.photographer_nr == nr && chicken.Lang == lang
select new
{
chicken.photographer,
chicken.Code,
chicken.Title,
Photo = (from cp in data.chicken_photos
where cp.chicken == chicken.Code
orderby cp.Sort
select cp.Photograph_Nr).FirstOrDefault()
};
If your tables have proper primary and foreign key relationships, and proper navigation associations in Entity Framework then you can also achieve the same results this way:
var q = from chicken in data.chickens
where chicken.photographer_nr == nr && chicken.Lang == lang
select new
{
chicken.photographer,
chicken.Code,
chicken.Title,
Photo = c.chicken_photos.Select(cp => cp.Photograph_Nr).FirstOrDefault()
};
And finally, to stay completely consistent and use only lambda-expressions:
var q = data.chickens
.Where(c => chicken.photographer_nr == nr && chicken.Lang == lang)
.Select(c => new
{
c.photographer,
c.Code,
c.Title,
Photo = c.chicken_photos.Select(cp => cp.Photograph_Nr).FirstOrDefault()
}
);
I prefer relying on entity navigation, as it forces the developer to create proper navigation associations in Entity Framework and proper foreign key relationships in the database. This will almost always result in optimized SQL underneath.
It's not always up to the developer how the database is structured, so you may have to stick with the first approach and write the sub-select yourself.
I figured it out.
Pretty obvious actually, too obvious :)
var q = from chicken in data.chickens
where chicken.photographer_nr == nr && lang == chicken.Lang
select new { chicken.photographer, chicken.Code, chicken.Title,Photo = (from b in data.chicken_photos where b.chicken==chicken.Code orderby b.Sort select b.Photograph_Nr).FirstOrDefault() };
var photo = (from c in chicken_photo where c.code = chicken orderby c.sort select c.chicken_nr).Take(1).SingleOrDefault();
You should really flesh out your question more...

How can I perform this query using L2E?

I have a 2 tables:
Activities ActivityKeywords
********** ****************
ID --> ActivityID
Name Keyword
I need to return all activities that match a specific keyword.
var q = from a in Context.Activities
where a.Keywords.Any(k => k.Keyword == someKeyword)
select a;
As I said in comments, it's nearly always wrong to use join in LINQ to Entities. The relationship properties should be used instead.
checkout the answer by Craig Stuntz for a cleaner way if you have a relation defined
My previous response was wrong but this works for me.
var activities = from a in db.Activities
join ak in db.ActivityKeywords on a.ID equals ak.ActivityID
where ak.Keyword == "yourkeyword"
select a;
I think you need something like
Give me all Activities which ID are in a list of ActivitiyKeywords.ID's
If that is your question, the you can try this:
var ids = from k in db.ActivityKeywords select k.ActivityID;
var result = from a in db.Activities where ids.Contains(a.ID) select a;
More information here.
var results = (from a in Activities
from k in ActivityKeywords
where k.Keyword == "keyword" && k.ActivityID == a.ID
select a).Distinct();

Categories

Resources