Need help building an Entity Framework 4 query - c#

My context model has a couple of related tables:
CREATE TABLE "CarSystem"."Reads" (
"ReadId" UUID PRIMARY KEY,
. . .
);
CREATE TABLE "CarSystem"."Alarms" (
"AlarmId" UUID PRIMARY KEY DEFAULT UUID_GENERATE_V4(),
"ReadId" UUID NOT NULL REFERENCES "CarSystem"."Reads" ( "ReadId" ),
. . .
);
There are other columns, but they're not important. There is a zero to many relationship between the Reads table and the Alarms table. There can be any number of rows in the Alarms table for each row in the Reads table, from zero on up.
I've got an Entity Framework model for this database structure. I've also got a ViewModel object for the rows in the Reads table. I want the ViewModel object to have a boolean property called HasAlarms. This property is to be set to true if there is at least one row in the Alarms table for the row in the Reads table.
I've got a function in my data access layer which is supposed to return an array of Read ViewModel objects that all match a set of criteria. I'm not sure how to construct the query to set the HasAlarms property. I only want to go to the database once and I want one entry in the array for each row in the Reads table.
Right now I'm making two database queries, one to retrieve all of the Reads and another to retrieve all of the Alarms:
IQueryable<Read> query = from read in context.Reads
where SomeCondition
select read;
Alarm[] alarms = ( from read in query
join alarm in context.Alarms on read.Readid equals alarm.ReadId
select alarm ).ToArray();
ReadViewModel[] result = ( from read in query
select new ReadViewModel {
ReadId = read.ReadId,
. . .
HasAlarms = alarms.Where( a => a.ReadId == read.ReadId ).Any(),
. . .
} ).ToArray();
This works, but it's inefficient because I'm hitting the database twice, once to retrieve the rows in the Reads table and once to get the Alarms.
Is there a way to build this query so it only hits the database once?
Tony
#Craig Stuntz:
What I'm trying to do is to speed up the rate at which data is loaded in my application in response to a report request. This is a WPF application and I need the data to load as quickly as possible to improve the user experience. It's important to make as few trips to the database as possible or the application seems to crawl.
The ReadViewModel object consists of properties that map to columns in the table, plus a couple of nested objects that are either stored as columns in the same table or as rows in a couple of related tables. It is a complicated structure and Entity Framework complains if I try to create the View Model objets with one IQueryable. That is, something like:
ReadViewModel[] reads = ( from read in context.Reads
join alarm in context.Alarms on read.ReadId equals alarm.ReadId
where SomeCondition
select new ReadViewModel { ... } ).ToArray();
throws an exception that says Entity Framework can't create a constant of one of the nested types.
If I retrieve the data into arrays of Entity Objects and then create the View Model objects using Linq, everything works. But then I have to make more than one trip to the database to get everything. If I retrieve all of the data with those queries, though, it's a lot faster than letting Entity Framework go back and query for the extra data for each row, which is what happens when I do it the way you recommend. There's also the complication of having to do a left outer join with the Alarms table to mess things up.
I've found that if I retrieve the arrays of Entity Objects first, instead of making one trip for each row in addition to the initial trip, I can make 2 or 3 trips total. It's much faster than making n + 1 or n + 2 trips. I was just trying to see if there was a way I could get Entity Framework to do it all in one database call, which I could easily do if I were writing the SQL myself. I'd just have to add a column that returns 0 or 1 for HasAlarms if there was at least one row in the Alarms table for the Read.

Use the navigations/relationships in your model. It's usually wrong to spell out joins in L2E.
ReadViewModel[] result = ( from read in context.Reads
where SomeCondition
select new ReadViwModel
{
ReadId = read.ReadId,
// . . .
HasAlarms = read.Alarms.Any(),
// . . .
} ).ToArray();

Related

migrating an access multi valued field column to c#

I am attempting to use the Microsoft.ACE.OLEDB.12.0 driver to read data from an access database. came upon an odd situation. one of the columns in the access database shows as a comma delimited list of ids.
Wells
________
345,456,7
6,387
when I looked at the column definition in access I thought it would say string but it does not, it says number. so I guess it is storing an array of integers in a single column?
I'm having a tough time getting a data reader to pick this up.
using
var w = DB_Reader.GetValue(DB_Reader.GetOrdinal("Wells"));
results in the error
The provider could not determine the Object value. For example, the
row was just created, the default for the Object column was not
available, and the consumer had not yet set a new Object value.
Well, at the end of the day, you can think of the mutli-value column as in fact a child table.
So, if you looking to migrate a master and child table, then in YOUR database, you need a relational set of tables to re-create what Access is doing behind the scene.
So, lets take a multi-value example and query.
Say we have this sql query in Access:
SELECT ID, Person_Name, FavorateColors FROM tPerson;
But, "favorite colors" is one of those MV columns. (and I should point out with the HUGE movement towards no-sql databases - they also often work this way also - same for XML or JSON data for that matter. However, be it some XML, JSON or Access mutli-value features? Well, you need that child table if you going to adopt a relational data model to represent this data.
Ok, so we run the above query, and you get this output:
In fact, when I used the lookup wizard - I picked a child table called tblColors.
but, how can we explode the above query to dig out the data?
Change the above query to this:
SELECT ID, Person_Name, FavorateColors.Value FROM tPerson
Note how we added ".value" after the MV column name. Now, when you run the query, you get the SAME result as if you had two tables, and did a left join. The parent table rows will like any relational database simple repeat for each child table value, and you get this:
Note how now the PK value and the row is repeating for each child mv value.
So, you are quite much free to query as per above - you get what amounts to a left joined table, and of course the parent record repeats.
So, just like XML, JSON, or in fact a query or a table of data with repeating parent row, and child rows? Well, you quite much forced to write code to split out this data, or re-normalize the data. This of course is far more common when receiving say JSON/XML data, or in fact often say data from a Excel sheet.
So, you have to process out the child record data, and create a relation for that data.
And thus now our question becomes how can we import JSON/XML/Excel data that really should have used two relational database tables.
So, assuming we want to process this data? You process it the same as for any data you have that should have been two related tables in the first place.
it really depends if this is a one time import, or you have to do this all the time?
If it was a one time deal, then I would use Access, and use a make table query based on the above query. You would in fact have to pluck up the PK ID from the child table. In above there is a child table called colors - we just missing that "junction" table in between that Access automatic created. The hidden tables are not exposed, and thus I would simply use a make table query in access, and then add a FK column that is the PK value from the tblColors.

How To can Select**DB Table

If I have a database in each table where the ID field and its appropriate function in any field do not take the administrator behavior so that tables and field contents can be fetched until the serial number is unified without duplicate values
Appropriate in this context using except.
Is there a code that can fetch tables either in sql or in the Entity Framework ؟
Eexcept_Admin_except_List
List<int> tempIdList = answeripE.Select(q => q.ID).ToList();
var quslist = db.Qustion.Where(q => !tempIdList.Contains(q.ID));
\Thanks for the creator of "daryal" Get All Except from SQL database using Entity Framework
I need to do this without asking for each table and querying it. And also request SQL from the database as a whole without exception such as
select*
IDfield
FROM
MSDB_Table T
WHERE
T.id == MaxBy(T.OrderBy(x => x.id);
can replace "where TABLE1.id 'OR' Table2.id" decode all the tables and give a result.
All I'm looking forward to is that I can query one database on a whole, get it on a list without the use of tables or a composite key because it serves me in analyzing a set of data converted to other data formats, for example when representing a database in the form of JSON There are a lot of them on more than one platform and in a single database and to avoid the repetition of the data I need to do this or a comprehensive query may be compared or to investigate or like Solver Tool in Excel, so far did not get the answer to show me the first step is because it does not exist originally or because it is not possible?
If you want Entity Framework to retrieve all columns except a subset of them, the best way to do that is either via a stored procedure or a view. With a view you can query it using LINQ and add your predicates in code, but in a stored procedure you will have to write it and feed your predicate conditions into it...so it sounds like a view would be better for you.
Old example, but should guide you through the process:
https://www.mssqltips.com/sqlservertip/1990/how-to-use-sql-server-views-with-the-entity-framework/

Setting a primary key with ROW_NUMBER in a view mapped with Entity Fluent API makes linq timeout

My problem is the following : I map my view to an object through Entity Fluent API. I needed a view containing an few left joins, an there were no unique identifier in the tables, therefore Entity always returned the same set of object. In a few different threads / blogs, I saw a solution consisting of add a column with
ROW_NUMBER() OVER (ORDER BY Id))
I then tried to map it in Entity :
in my class I add a property
public long Row { get; set; }
and in my configuration class I add
HasKey(imc => imc.Row).HasColumnName("Row")
Apparently, the mapping works. What doesn't work is that, when I query the objects with linq, even a Count() will timeout ; however the request itself only returns about 200 lines when used in a SQL Management Studio environement.
Has anyone ever seen this issue ?
EDIT:
I have been able to bypass the problem by replacing the "row_number()" with a newid() in the MS SQL View, but I'm still afraid it might be a problem later on.
Your query is slow which causes the timeout. About 1 million people have seen this before. You would need to analyze the query plan. Computing a row number over the whole table if unindexed can be slow. Also, a row number cannot be used as a key because it's values changes when you change the underlying data. EF does not support changing keys.
If you use newid() as the "key" in the view then you get fresh IDs each time. I think you might not be aware of the fact that a view is merely a shortcut for that particular query. It's contents are not stored anywhere.
Introduce a column that can be used as a key. For example an IDENTITY column.

Best way to check if multiple records exist in database

I am creating an application that takes data from a text file which has sales data from Amazon market place.The market place has items with different names compared to the data in our main database. The application accepts the text file as input and it needs to check if the item exists in our database. If not present I should throw an option to save the item to a Master table or to Sub item table and map it to a master item. My question is if the text file has 100+ items should I hit the database each time to check if the data exists there.Is there any better way of doing that so that we can minimize the database hits.
I have two options that i have used earlier
Hit database and check if it exists in table.
Fill the data in a DataTable and use DataTable.Select to check if it exists.
Can some one tell me the best way to do this?. I have to check two tables (master table, subItem table), maybe 1 at a time. Thanks.
Update:
#Downvoters add an comment .
i am not asking you whats the way to check if an item exists in database.I just want to know the best way of doing that. Should I be hitting database 1000 times if an file has 1000 items? That's my question.
The current query I use:
if exists (select * from [table] where itemname= [itemname] )
select 'True'
else
select 'False'
return
(From Chat)
I would create a Stored Procedure which takes a table valued parameter of all the items that you want to check. You can then use a join (a couple of options here)* to return a result set of items and whether each one exists or not. You can use TVP's from ADO like this.
It will certainly handle the 100 to 1000 row range mentioned in your post. To be honest, I haven't used it in the 1M+ range.
in newer versions of SQL Server, I would prefer TVP's over using an xml input parameter, as it is really quite cumbersome to pack the xml in your .Net code and then unpack it again in your SPROC.
(*) Re Joins : With the result set, you can either just inner join the TVP to your items / product table and check in .Net if the row doesn't exist, or you can do an left outer join with the TVP as the left table, and e.g. ISNULL() missing items to 0 / 'false' etc.
Make it as batch of 100 items to the database. probably a stored procedure might help, since repetitive queries has to be fired. If the data is not changed frequently, you can consider caching. I assume you will be making service calls from ur .net application, so ingest a xml from back end, in batches. Consider increasing batch size based on the filesize.
If your entire application is local, batch size size may very high, as there is no netowrk oberhead, still dont make 100 calls to db.
Try like this
SELECT EXISTS(SELECT * FROM table1 WHERE itemname= [itemname])
SELECT EXISTS(SELECT 1 FROM table1 WHERE itemname= [itemname])

Combining multiple rows into one entity in Entity Framework 4.1

I've been trying to grow my EF understanding from just querying tables to creating Entities that match my business objects so I can code against my business objects rather than my data objects. I read articles that suggest this is possible, but all of their examples are rather trivial and involve just combining two tables. My situation is a little more complicated and I'm not sure how to proceed.
I have two tables (simplified below)
CREATE TABLE [dbo].[BarEvents]
(
[BarGUID] UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID(),
[Bar] INT NULL
)
CREATE TABLE [dbo].[BarLog]
(
[BarGUID] UNIQUEIDENTIFIER NOT NULL,
[BarLogGUID] UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID(),
[BarEventTime] DATETIME NOT NULL DEFAULT GETUTCDATE()
)
So if I join these tables, for a specific BarGUID, so if I had 1 Bar and 4 bar events logged, I'd have 4 rows, but what I want is just the most recent BarEventTime. So I would like to join and have just one row:
I can do this trivially in EF:
var query = barEntities.BarEvents.Where( q=> q.BarGUID = '0000-0000-0000-0000')
.Select(barEvent =>
new LogItem()
{
Bar = barEvent.Bar,
BarEventTime = barEvent.BarLog.Max(u => u.BarEventTime)
});
But from what I've read, I should be able to define a LogItem entity, and place this logic somehow in my LogItem entity, then write queries against that. My problem is I only see trivial join conditions when I'm trying to join my tables in the entity definitions. Is there a way to do this? Or a guide?
Any help would be appreciated.
Thank you.
Why don't you do the following:
Create a SQL View in the Database that does what you want
Add the view to your EF Context
Use the newly created entity that is based on the view

Categories