LINQ IQueryable Nested Loops - asp.net

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();

Related

Drupal \Drupal\user\Entity\User how retrieve property

i come from ES6 and need to do something in one Drupal 8 site.
Basically I try to get some value from the current logged user object.
...i try any possible method but nothing good.
by this snippet of code i can dump($userx) variable, i need to parse
$userCurrent = \Drupal::currentUser();
$uid = $userCurrent->id();
$userx = \Drupal::entityTypeManager()->getStorage('user')->loadByProperties([
'uid' => '13465'
]);
dump($userx);
outpup see picture
$cf = $userx->get('field_codice_fiscale_user')->getvalue()[0]['value'];
dump($cf);
otput NULL
Results output
i need the value of
protected values
field_cv_codice_fiscale
x-default => array (1)
0 => array (1)
value => string (16) "DSSSLV83D67B35QV"
i tried:
$cf = $userx->get('field_codice_fiscale_user')->getvalue()[0]['value'];
again NULL
my goal is to have variable valorized by :
'field_codice_fiscale_user' -> value;
after struglling two days i need to give up to drupal folly.
Thank you in advance
I found the solution.
as reported in the Drupal specification, entityTypeManager return objects array.
so the corect snippet is:
$userx = \Drupal::entityTypeManager()->getStorage('user')->loadByProperties([
'uid' => $uid2 ]);
dpm($userx);
$cfx = $userx[$uid2];
now the variable $cfx contain objects (inpictures = '3465' objects).
we can access the object property by this way
if(isset($cfx->get('field_codice_fiscale_user')->getvalue()[0]['value'])) {
$cf = $cfx->get('field_codice_fiscale_user')->getvalue()[0]['value'];
} else { $cf = '';}
dmp($cf)
output
$scf = 'DSLL....'

How can i select distinct using one field

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())

Can't get Plan or Plan.Name from Stripe.Net Invoice using Linq

I need to use something like Linq to Select specific Invoice data coming from Stripe.Net. m.Description is null, so I need to get the Description from Plan.Name, which is contained here StripeInvoiceLineItems.Data.Plan.Name. Here is my code.
//Get Invoices
var invoices = StripeHelper.GetAllInvoices(merchant.StripeCustomerId);
var convertInvoices = invoices
.Select(m => new Stripe.StripeInvoice
{
Id = m.Id,
Description = m.StripeInvoiceLineItems.Data.Where(i => i.InvoiceId == m.Id).Select(i => i.Plan.Name).ToString(),
StripeInvoiceLineItems = m.StripeInvoiceLineItems,
Date = m.Date,
Paid = m.Paid,
Total = m.Subtotal,
NextPaymentAttempt = m.NextPaymentAttempt,
})
.ToList();
This doesn't work either.
m.StripeInvoiceLineItems.Data[0].Plan.Name
There is no error. I just don't get any data and I'm trying to get the Description of the Invoice using Plan.Name.
Any help is much appreciated Thanks!
You should use FirstOrDefault instead of Where:
Description = m.StripeInvoiceLineItems.Data
.FirstOrDefault(i => i.InvoiceId == m.Id)
.Plan.Name;
Where return type is Queryable and using ToString() on these types does not make sense.

NHibernate QueryOver - Doing Fetches and OrderBy -> What Syntax to use?

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.

Adding an array of an array at Amazon DynamoDB

I know that AmazonDB supports number, string, number set and string set as item types. But, how about a set of an string set (array of array, or multidimensional array)?
In case it's possible, this is the only way I found to do that, which didn't work (using PHP):
$units_frequencies["id"][0] = "400";
$units_frequencies["id"][1] = "401";
$units_frequencies["id"][2] = "402";
$units_frequencies["frequency"][0] = "20";
$units_frequencies["frequency"][1] = "30";
$units_frequencies["frequency"][2] = "50";
// item that will be inserted
$item = array(
'id' => array(AmazonDynamoDB::TYPE_STRING => $id),
'arrays_field' => array(
AmazonDynamoDB::TYPE_ARRAY_OF_STRINGS => array(
AmazonDynamoDB::TYPE_ARRAY_OF_STRINGS => $units_frequencies)));
I don't want to have two columns (one for $units_frequencies["id"] and $units_frequencies["frequency"]) because the second one can have two index with the same values, which is not allowed by Dynamo.
Thanks in advance.
It doesn't.
At least while looking at AttributeValue.class (AWS Java SDK)
I also couldn't find any hint on the documentation site except for those dealing with int, string, set of string or set of int
You can eventually serialize your object. More info at https://java.awsblog.com/post/Tx1K7U34AOZBLJ2/Using-Custom-Marshallers-to-Store-Complex-Objects-in-Amazon-DynamoDB

Resources