Entity Framework Projection translation failure GroupBy - sql-server

I've been cleaning up some Entity LINQ Method queries, to try and optimize generated queries in a project, and was attempting to avoid a JOIN, by GROUP BY of a foreign key. But ran into an unexpected projection failure with Entity Framework.
Using the demo database in LINQPAD 7, here's an example of the original query and how I'm attempting to optimize it.
Works:
Albums
.Select(a => a.Tracks.OrderBy(t => t.Milliseconds).First())
.Select(g => new { g.Name, g.Composer })
.Dump();
Runtime Exception:
Tracks.GroupBy(t => t.AlbumId)
.Select(g => g.OrderBy(t => t.Milliseconds).First())
.Select(g => new { g.Name, g.Composer })
.Dump();
Now I understand I can do the following, but it makes a very odd SQL query (that joins to itself) and isn't as clean to read as the failing example.
Tracks.GroupBy(t => t.AlbumId)
.Select(g => g.OrderBy(t => t.Milliseconds).Select(g => new { g.Name, g.Composer }).First())
.Dump();
Can anyone explain why Entity Framework doesn't like the GroupBy followed by a selection, and a projection? While a similar join to a table works fine?
The optimal query I'm looking for is:
SELECT Name, Composer
FROM (
SELECT Name, Composer, ROW_NUMBER() OVER(PARTITION BY AlbumId ORDER BY Milliseconds) AS row
FROM Track
)
WHERE row <= 1

I have noticed that if you change query order, the exception does not occur...
Change this:
Tracks
.GroupBy(t => t.AlbumId)
.Select(g => g.OrderBy(t => t.Milliseconds).First())
.Select(g => new { g.Name, g.Composer })
.Dump();
With this:
Tracks
.OrderBy(x => x.Milliseconds)
.GroupBy(x => x.AlbumId)
.Select(x => new {
x.FirstOrDefault().Name,
x.FirstOrDefault().Composer
})
I think it's because you're trying to sort lists within groups, when you should be sorting all results first and then grouping, though I'm not entirely sure. This, if it wasn't linq to sql, would work just fine.

Related

jdbc logstash Change table name to today

I want the table name to be today's date.
For example: dbtest_2022.dbo.tbshop2_2022_08_22 auto change to dbtest_2022.dbo.tbshop2_2022_08_23
input {
jdbc {
jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/sqljdbc42.jar"
jdbc_driver_class => "com.microsoft.sqlserver.jdbc.SQLServerDriver"
jdbc_connection_string => "..."
jdbc_user => "..."
jdbc_password => "..."
statement => "SELECT ... FROM dbtest_2022.dbo.tbshop2_2022_08_22"
schedule => "*/14 * * * *"
add_field => { "tag" => "mssql-test" }
type => "mssql"
}
}
I had an idea to make two requests.
In the first request, get the table id and in the second, make a request with this id.
statement => "SELECT OBJECT_ID(N'dbtest_2022.dbo.tbshop2_{year}_{month}_{day}') AS 'object_id' AND SELECT ... FROM table(object_id)"
or is there any expression in jdbc to implement this?
For example: dbtest_2022.dbo.tbshop2_now()
or can I use dbtest_2022.dbo.tbshop2_{year}{month}{day} in jdbc ?
Well, so that every day you don’t change the request with your hands, but somehow automate it
I am not very good at SQL. I would be glad for help or ideas on how to implement this.
I solutioned with below steps.
1. [.profile] set Envoronment variable.
...
CURRENT_YYYYMM=`date "+%Y%m`
export CURRENT_YYYYMM
...
2. logstash config file
input {
jdbc {
...
FROM ${CURRENT_YYYYMM}_logs
...
}
reference :
https://www.elastic.co/guide/en/logstash/current/environment-variables.html

On knex migration:up, table.foreign is not showing up on the actual table on the terminal

I have setup knex migration to create two tables
export async function up(knex: Knex): Promise<void> {
const table1 = await knex.schema.hasTable('users');
if (!table1) {
await knex.schema.createTable('users', (table) => {
table.increments("id").primary();
table.string("username");
table.string("email");
table.string("password");
table.string("role");
table.timestamp("created_at");
table.timestamp("updated_at");
table.timestamp("logged_at");
});
}
const table2 = await knex.schema.hasTable('usersloc');
if (!table2) {
await knex.schema.createTable('usersloc', (table) => {
table.increments("locid");
table.string("lat");
table.string("lng")
table.foreign("userid");
});
}
}
However, when I did a select * from usersloc;, userid in usersloc is nowhere to be found.
My intention is to have it referred to the id at the "users" table.
Any idea what happened?
Solution found - looks like the UUID needs to have a .unique() reference on both tables. My guess is that even though UUID may take billions of years to have 1% chance of collision, it is still not a unique ID, thus a .unique() reference is needed.

is there a solution to fetch all id in the Firestore?

i want to fecth all the id not just 888888888 and get the orders for each id
What you're describing is known as a collection group query in Firestore.
It'd looks like this:
db.collectionGroup("orders").get()
The above reads all collections called orders no matter where they are located (top-level, under an tels doc, or under any other doc.
To determine what tels doc a specific order is under, you can navigate up ref.parent.parent of the order snapshot:
db.collectionGroup("orders").get().then((querySnapshot) => {
querySnapshot.forEach((orderSnapshot) => {
const orderRef = orderSnapshot.ref;
const ordersRef = orderRef.parent;
const telRef = orderRef.parent;
console.log(refRef.id); // 8888888888
})
})

Cakehp 2.3.9 hasMany different table name

I'm at a loss here the situation is as follows i have 2 tables:
filter and widget (yes none cake table names which im not allowed to change)
Now filter belongs to widget and widget has many filters both models show up in pr() like this.
[name] => Filter
[useTable] => filter
[belongsTo] => Array
(
[Widget] => Array
(
[className] => Widget
[foreignKey] => id
[conditions] =>
[fields] =>
[order] =>
[counterCache] =>
)
)
and filter
[name] => Widget
[useTable] => widget
[hasMany] => Array
(
[Filter] => Array
(
[className] => Filter
[foreignKey] => widget
[conditions] =>
[fields] =>
[order] =>
[limit] =>
[offset] =>
[dependent] =>
[exclusive] =>
[finderQuery] =>
[counterQuery] =>
)
)
Now the problem is as follows when i do a simple:
pr($this->Filter->findById(1934));
or
pr($this->Widget->findById(1663));
I get an error:
Missing Database Table
Error: Table analyse_widgets for model Widget was not found in datasource default.
But when i use this code it works fine, but this is just to ugly to use evrytime i want to find something:
$this->Widget;
pr($this->Filter->findById(1934));
pr($this->Widget->findById(1663));
I have no idea how to get this working like it should be. Is it because of the none caketable names ? or is it something i forgot ?
This is what im loading the models with and clearing model cache had no influence:
App::uses('Analyse.Filter', 'Model');
App::uses('Analyse.Widget', 'Model');
$this->uses = array('Analyse.Widget', 'Analyse.Filter');
Any insight in the situation would be greatly appreciated
Try this...
App::uses('Filter', 'Model');
App::uses('Widget', 'Model');
$this->uses = array('Widget', 'Filter');
Add $useTable in your model ie.
public $useTable = 'widget';
public $useTable = 'filter';
Hope it will help you!
Seem's when you use a hasMany or belongsTo with custom tablenames cake still makes it's own models to rely on. Unless you recast them again just before a find function which happend whith: $this->Filter and $this->Widget
I made a workaround by putting this in the beforeFilter but its only needed when you use a relation with none cake table names.
$this->Filter->useTable = 'filter';
$this->Widget->useTable = 'widget';

Why would my entity not return with updated values?

I have a Customer entity defined in EF Code First with an AccountNumber property. I can get and update a single Customer with their AccountNumber without issue. But when I get all Customers the AccountNumber is old for sometime and then eventually updates after a change. The database always returns the correct AccountNumber value.
I have profiled SQLServer and found that the call to get all Customers does make it to the database and it returns the latest value but the response from the DbContext gives an old AccountNumber. So it seems like EFCF is caching my data.
Please help.
UPDATE: Code examples -
public IQueryable<Customer> GetCustomers()
{
return this.acmeDbContext.Customer
.Include(x => x.IpAddressRange)
;
}
public Customer GetCustomer(Guid id)
{
var Customer = this.acmeDbContext.Customer
.Include(x => x.Contacts)
.Include(x => x.IpAddressRange)
.OrderByDescending(x => x.Id)
.FirstOrDefault(x => x.CustomerId == id);
return Customer;
}
public void SaveCustomer(Customer Customer)
{
this.acmeDbContext.SaveChanges();
}
I ended up using the Reload method to reload each customer:
if (noCache)
customers.ToList().ForEach(x => acmeDbContext.Entry(x).Reload());

Resources