I need an example of linq to xml query.
I have two ListBoxes with SelectionMode set to Multiple.
My query for populating first ListBox is:
var query = doc.Root.Descendants("Articles")
.OrderBy(b => b.Element("Category").Value)
.Select(b => b.Element("Category").Value)
.Distinct();
and binding it with:
lbxItems.DataSource = query;
lbxItems.DataBind();
So i have all the values in first ListBox, and when i select item from that ListBox i want to populate second ListBox.
So on SelectedIndexChanged i have another query:
var query = doc.Root.Descendants("Articles")
.Where(b => b.Element("Category").Value.Equals(lbxItems.SelectedValue))
.OrderBy(b => b.Element("SubCategory").Value)
.Select(b => b.Element("SubCategory").Value)
.Distinct();
That's working if i select one item, but i need a query that is doing the same thing but from multiple selected items.
Thank you.
Try changing your where clause like so:
.Where(b => lbxItems.Items
.Cast<ListItem>() // needs a cast
.Where(i => i.Selected)
.Select(i => i.Value)
.Contains(b.Element("Category").Value))
The idea is to determine what items are selected and see if your category value is among those selected.
Related
How can i select distinct() based on one field?
I have the following LINQ expression, how can I select distinct by ID field. for some reason i used .Distinct() but keeps shown me a duplicate, I want to show just one record
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.Distinct()
.ToListAsync();
try:
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.Select(c => c.ID)
.Distinct()
.ToListAsync();
Distinct compare each column of the row, so if one column is different, the row is distinct for linq / sql.
You can try it with a GroupBy:
var customersbyName = await _context.vw_CustomerSearch.AsNoTracking()
.Where(c => c.Name.Contains(request.searchWord))
.GroupBy(i => i.ID)
.Select(x => x.First())
I have two Entities, First one is the Company Entity and the other one is Events Events Entity.
ManyToOne(targetEntity="App\Entity\Company", inversedBy="events"
On the events from I have created a drop-down doing something like following.
->add ( 'company' , EntityType::class , [
'class' => Company::class ,
'choice_label' => function ( Company $company ) {
return $company->getName ();
}
is there any way I can obtain other values from the database for the selected company. In the database, there is a column called app_client_id which I want to get on dropdown selection so I can use that to call external API'S.
By default, in the dropdown, you get the result of the __toSring() function in the entity. Consider setting there what you want to read when selecting.
I am trying to replicate this loop as an IQueryable:
foreach (var book in BookList)
{
foreach (var a in book.Authors)
{
if (a.AuthorId.ToString() == Id)
{
AuthorView = new AuthorViewModel(a, item.BookId);
}
}
}
I have tried:
var Test = _context.Book.Include(x => x.Authors)
SelectMany(y => y.Authors).ToList().FirstOrDefault(x => x.AuthorId.ToString() == Id)
.Select(x => new AuthorViewModel(x, ??.BookId);
But I get stuck trying to create the object AuthorViewModel as it requires the BookId that I can no longer access. Is there a way of passing the book Id down?
Sorry, just release the example doesn't make sense.
Books is a table in a database.
Authors is a table in the database which contains many authors.
Book:
BookId
Authors
Authors:
AuthorId
Name
DOB
AuthorList should have been BookList (List). I have corrected this.
I am trying to locate an author based on an author id - and return it in an object (Author, BookId (from the book table))
This is I would do:
var id= int.Parse(Id);
var Test = _context.Book.Include(x => x.Authors)
.SelectMany(item => item.Authors
.Where(y => y.AuthorId == id)
.Select(b => new AuthorViewModel(b,item.BookId));
You can filter and project inside of the SelectMany extension method
I think you don't need SelectMany or Include at all. You can go like;
_context.Book
.Where(b => b.Authors.Any(a => a.AuthorId.ToString() == Id))
.Select(b => new AuthorViewModel(b.Authors.FirstOrDefault(x => x.AuthorId.ToString() == Id), b.BookId);
If you drill down on the Authors (SelectMany) then you have no way to go back to books. The condition on AuthorId needs to be handled internally.
var Test = _context.Book.Include(x => x.Authors)
.FirstOrDefault(x => x.Authors.Any(y => y.AuthorId.ToString() == Id))
.Select(x => new AuthorviewModel(x,x.BookId);
of course this will select only one book per author, just like your code. I wonder if your desired behaviour is to get all books instead...
First of all, convert Id to a number instead of trying to convert AuthorId to a string. Applying any kind of function on a table field means that indexes that cover it can't be used. Instead of a fast search based on an ID, you'll have a full table scan that converts values to strings before comparing them using string semantics. If the Id parameter contains any leading zeros, the comparison will fail.
As for the LINQ query itself, the easiest way is to use the query form. If you want to return one record for each book and author combination, you can write :
var id=int.Parse("ID");
var query= from book in _context.Book
from author in book.Authors
where author.AuthorID = id
select new AuthorViewModel(author,book.BookId);
var records=query.ToList();
All,
I have a query as such:
_AddOrderBy(sortOptions, query)
.Fetch(x => x.ImageType).Eager
.Fetch(x => x.User).Eager
.Fetch(x => x.Partner).Eager
.Inner.JoinAlias(x => x.Partner, () => p).Fetch(x => x.Company).Eager
.Skip(startIndex)
.Take(pageSize)
.List<ImageRequest>();
In the above QueryOver I call _AddOrderBy() method which adds an order by clause. The challenge I face is how do I create an "order by" that references a property (ordering by "CompanyName") that lies within the following association path without conflicting with my Fetch()/Inner joins:
ImageRequest.Partner.Company.CompanyName
Inside my _AddOrderBy() I have this:
Partner p = null;
Company comp = null;
order = query.Inner.JoinAlias(x => x.Partner, () => p)
.Inner.JoinAlias(x => x.Company, () => comp)
.OrderBy(x => comp.CompanyName);
But this gives me a run time exception stating that I have duplicate key (referring to Partner) in the criteria. I can see that this is conflicting with my eager fetching.
My questions is:
How do I add an "order by" so it works with my Fetching.
The beauty of using an Alias in QueryOver is that you don't have to use Fetch or JoinAlias in your _AddOrderBy() method again if the Join happens in the query already. You only need to declare the Alias with the same name.
Therefore your _AddOrderBy() can just look like this:
Partner p = null;
Company comp = null;
order = query
.Inner.JoinAlias(x => p.Company, () => comp) // you can use p here if it was used in the query before
.OrderBy(x => comp.CompanyName);
The reason this works is this: If you put the whole code into one method it will obviously work. Splitting it into two methods still works, because Partner p is not a reference to an object in memory but an Alias that is simply translated into a string for the SQL query.
I am trying to modify the query for Views in Drupal (Views version 3, Drupal version 7).
What I want to do is change the query prior to running such that it LEFT JOINs a table in which I have weights assigned to the nodes.
If I was to write the query I want in SQL, it would look like this:
SELECT a.nid, a.title, a.description
FROM node a
LEFT OUTER JOIN node_weights b
ON a.nid = b.nid
WHERE b.uid = $uid
ORDER BY b.weight DESC
This query works like a champ when I run it in the query analyzer. So, now I need to make it work in my module.
I've seen multiple approaches detailed on various blogs for different ways to modify View queries, but they seem to be addressing different versions of Views. So it is very confusing to try to determine whether anything I'm looking at could even possibly work for my application.
It seems that I need to use a MODULE_NAME_views_tables() function to tell Views what the relationship is between the table I want to join and the node table.
I've added the following functions to MODULE_NAME.views.inc:
function MODULE_NAME_views_tables() {
$tables['node_weights'] = array(
"name" => "node_weights",
"join" => array(
"left" => array(
"table" => "node",
"field" => "nid"
),
"right" => array(
"field" => "nid"
),
),
);
return $table;
}
This does seem to be working because when I use Krumo to look at the query array, I see my "node_weights" table in the "table_queue" element.
In the views_query_alter() function, I'd like it to work something like this:
function MODULE_NAME_views_query_alter(&$view, &$query) {
$uid = $_COOKIE['uid'];
$view->query->add_relationship('node_weights', new views_join('node_weights', 'nid', 'node', 'nid','LEFT'));
$view->query->add_where('node_weights', "node_weights.uid", $uid);
krumo($query);
}
This function barfs pretty badly. Although my join table is appearing in the $view object, the add_relationship method is throwing an error for a 3rd argument, but I don't see any examples online that have 3 arguments so I don't know what it's missing.
Also, I'm pretty sure my add_where method isn't correct, but I don't know what the inputs should actually be. This is just a blind guess.
The bottom line is that I want to join the node table to my node_weights table, and then make sure my weights are used in the query to sort the results in a descending fashion where the user id = the user id in my table, and the tables are joined on the nid field.
Thanks in advance.
WHEREs are pretty easy to add once you've got the JOIN in. You can both in a query alter (Drupal 7).
function MODULE_NAME_views_query_alter(&$view, &$query){
// Only alter the view you mean to.
if($view->name == 'VIEW NAME' && $view->current_display == 'DISPLAY'){
// Create the join.
$join = new views_join();
$join->table = 'table_name';
$join->field = 'entity_id';
$join->left_table = 'node';
$join->left_field = 'nid';
$join->type = 'left';
// Add the join the the view query.
$view->query->add_relationship('table_name', $join, 'node');
// Add the where.
$view->query->where[1]['conditions'][] = array(
'field' => 'table_name.collumn_name',
'value' => 'value',
'operator' => '='
);
}}
I found the OP's comments helpful in creating a join in the hook_views_query_alter function, so I wanted to put the parts I found useful in a more digestible answer.
I was using Views 2x on Drupal 6x, but I assume it would be very similar to use on D7 Views 2.
The OP mentions describing the relationship of the join in hook_views_table. This wasn't necessary for me, as I was not linking to a custom table, but one that existed in core.
The join creation in the HOOK_views_query_alter() function was very helpful though:
$join = new views_join;
$join->construct('table_name',
'node', // left table
'nid', // left field
'nid', // field
)
See views_join::construct documentation for more information. In particular, I didn't need to use the 'extra' parameter that the OP used. Perhaps this is necessary with a custom table.
Finally, add the join to the query, and whatever other elements are needed from it:
// Add join to query; 'node' is the left table name
$view->query->add_relationship('table_name',$join,'node');
// Add fields from table (or where clause, or whatever)
$view->query->add_field('table_name','field_name');
...
You already have the $query in parameters, so you can just do:
myhook_views_query_alter(&$view, &$query) {
if ($view->name = ....) {
$join = new views_join();
$join->construct(
...
);
$query
->add_relationship(...)
->add_where(...)
->add_orderby(...)
...
;
}
No need to use $view->query->...