Entity Framework nested lambda query - asp.net

In Linq2Sql, it was possible to do a query such as:
using (var db = GetDataContent())
{
var query = from p in db.Brands
where p.Deleted == false
select new BrandImageSummary
{
BrandID = p.BrandID,
BrandUrl = p.BrandUrl,
Description = p.Description,
MetaDescription = p.MetaDescription,
MetaKeywords = p.MetaKeywords,
MetaTitle = p.MetaTitle,
BrandImageUrl = (from p2 in db.SiteImages where p2.FileTypeID == 5 && p2.ForeignID == p.BrandID && p2.Deleted == false orderby p2.Rank select p2.Filename).FirstOrDefault(),
Deleted = p.Deleted,
SupplierCode = p.SupplierCode,
Title = p.Title,
Website = p.Website
};
return query.ToList();
}
With BrandImageUrl being a nested select. Howerver in entity framework, I seem to get the error:
Unable to create a constant value of type 'SiteImage'. Only primitive
types or enumeration types are supported in this context.
Is there a way to do this in entity framework?
The idea of the query is to get one brand image, if I was to join, and there was multiple images, I would get multiple rows and I do not want this.
I am using Entity Framework 5.
Thanks for your help

You should create a one-to-many relation in your model classes.
You can then write
BrandImageUrl = p.BrandImages
.Where(i => i.FileTypeID == 5 && !i.Deleted)
.OrderBy(i => i.Rank)
.Select(i => i.FileName)
.FirstOrDefault()

Related

Symfony 3 one-to-many, get parent with all children if one child satisfy the codition

I have these two tables
I want to get all products(with all the children) that have at least one child with log_id = 13. Let's say I have the following rows in eorder_product_config table:
The function that retrieves the products looks like this:
public function getProducts($logId){
$q = $this
->createQueryBuilder('p')
->select('p', 'pc')
->where('pc.logisticStatus = :logId')
->setParameter('logId', $logId)
->getQuery();
return $q->getResult();
}
This will get the product(id = 18) with only 2 children(id = 46,48) in the productConfigs collection and I want have all 5 children if there is at least one that has log_id = 13.
I've found a workaround using subqueries:
public function getProducts($logId){
// search for configs that have log_id = 13
$subQuery = $this->createQueryBuilder('pp')
->select('DISTINCT pp.id')
->leftJoin('pp.productConfigs', 'ppc')
->leftJoin('ppc.logisticStatus', 'pls')
->where('ppc.logisticStatus = :logId');
//->andWhere('ppc.id = p.id'); // used for EXIST query method
// main query
$q = $this->createQueryBuilder('p');
$q->select('p', 'pc');
$q->leftJoin('p.productConfigs', 'pc')
// inject subquery, check to see if current product is in
// the subquery result
$q->where($q->expr()->in('p.id', $subQuery->getDQL()));
//$q->where($q->expr()->exists($subQuery->getDQL()))
$q->setParameter('logId', $logId);
return $q->getQuery()->getResult();
}
***I've seen that using the EXIST query does't work as it should that's why I choose the IN query. But in the raw sql query they both return same results.

Equivalent IN operator in entity framework

var query = from c in context.Albums
where c.AlbumID in albumIds
select c.Albumname;
Here albumIds is IENUM<> of some custom type(in my case its an Entity)
When I do the above query I get an error
Operator == cannot be applied to type int and IEnumerable
This error is acceptable but how do I overcome this
Turn it around slightly - you want to check whether your enumerable of album ids contains the id of an album you have just iterated to in your linq. So something like this ...
albumIds = {1,2,13,25,277,567};
var query = context.Albums.Where(x=> albumIds.Contains(x.ID));
(Sorry, writing example code without a tool in front of me so forgive any obvious mistakes. Hopefully you can get the idea from this though).
var albumIds= new string[] { "900", "801", "802", "803","906" };
var lstData = context.tbl.Where(
x => (x.TimeCreated >= yesterday && x.TimeCreated < today) &&
albumIds.Contains(x.TransactionSetId)
).Select(x => x.X12_Interchange).ToList();

Convert SQL to LINQ query to get max

hi guys i am stuck converting below sql to LINQ query.
all i want is to have maximum number from list of (FA-00001 ,FA-00059)
SELECT MAX(CAST(SUBSTRING(ReferenceId, PATINDEX('%-%', ReferenceId) + 1, LEN(ReferenceId) - PATINDEX('%-%', ReferenceId)) AS int)) AS MaxReferenceId FROM [ClientRC].[dbo].[EHO_Action]
is this possible to convert to LINQ? thanks
An alternative approach using anonymous projection:
var y = (from record in
(from record in db.ClientRC
select new
{
Group = "x",
ReferenceNumber = Convert.ToInt32(record.ReferenceId.Split('-')[1])
})
group record by new { record.Group } into g
select new
{
MaxReferenceId = g.Max(p => p.ReferenceNumber)
});
http://msdn.microsoft.com/en-us/library/bb386972.aspx
var myvar = (from v in db.object where v!=null select v.id).Max();
MSDN has lots of examples for stuff like this.
Or, you can execute queries directly against a datacontext if you're using entity framework. Just make sure if you're doing anything with parameters you're parameterizing the query and not taking user input directly into it.
http://msdn.microsoft.com/en-us/library/ee358769.aspx
Try this..
var list = DBContext.EHO_Action
.Where(x => x.YourListColumn != null)
.Select(x => x.YourListColumn).ToList(); // Take the list (FA-00001 ,FA-00059) from db to a list
var maxNo = list.Max(x => Convert.ToInt32(x.Split('-')[1]));
Please change the context and column names according to your Linq context.
If you want to use sql you can do it this way..
var list = DBContext.ExecuteQuery<string>("select yourreqrdcolumn from [ClientRC].[dbo].[EHO_Action]");

Linq To Sql Get data into Label

I have a label to show BookName. I get it from table which name tblBooks. I don't know how to show Book Name into the label.
var query = from b in dc.tblBooks.Where(b=>b.BookID == 'B01') select b;
Can you help me know.
Your query as written will return a collection of books—IQueryable<Book>. If you're sure there will only be one result in this query, you can call SingleOrDefault, which will execute the query immediately and give you the actual book.
var Book = dc.tblBooks.Where(b => b.BookID == 'B01').SingleOrDefault();
if (Book != null)
myLabel.Text = Book.BookName;
Or you can simply say:
var Book = dc.tblBooks.SingleOrDefault(b => b.BookID == 'B01');
Which does the same thing.
If you're 110% sure there will always be a result, and you don't want to check for null, then you can use Single, which will do the same thing, except throw an exception if no results are found, where SingleOrDefault simple returns null.
var Book = dc.tblBooks.Single(b=>b.BookID == 'B01');
myLabel.Text = Book.BookName;
Try:
label.Text = query.FirstOrDefault().BookName;

LINQ sorting, doesn't work

I have a LINQ query like this:
from i in _db.Items.OfType<Medium>()
from m in i.Modules
from p in m.Pages
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
select p
I use the query like this because I have strongly typed view (ASP.NET MVC).
I need to have items sorted by the i.Sort property. orderby i.Sort and i.OrderBy(it => it.Sort) doesn't work. How can I fix this?
When sorting with Linq you usually give OrderBy a property, and eventually an IComparer, not a sorting function. For example:
class Person {
public int Age {get; set;}
}
public static void Main() {
var ps = new List<Person>();
ps.Add(new Person{Age = 1});
ps.Add(new Person{Age = 5});
ps.Add(new Person{Age = 3});
var sorted = ps.OrderBy(p => p.Age);
foreach(p in sorted) {
Console.WriteLine(p.Age);
}
}
Here Linq will know how to correctly sort integers.
Without giving more context (such as what exactly is i.Sort, what is its purpose, what do you want to do with it), it would be difficult to be more specific to your problem.
However, I'm pretty sure you are misunderstanding OrderBy: you should give it a lambda expression that identifies a property of the objects contained in your sequence, and then Linq will sort your sequence according to the usual order of the type of that property (or according to another order you define for that type, by using IComparer).
Let's say your Pages include page-numbers among their properties. Let's pretend this property is called "pagenumber". You would then add the following 'orderby' line between the 'where' and 'select' lines.
// (snip...)
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
orderby p.pagenumber
select p
Or maybe you don't have page numbers, but only page titles. You would do nearly the same thing:
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
orderby p.title
select p
Just from reading your code, I can't tell what criteria should be used for sorting. You need some kind of ordered element, an id number, a page number, or some text can be alphabetized.
from i in _db.Items.OfType<Medium>().OrderBy(x => x.Sort)
...

Resources