I'm trying to implement Server mode in one of Devexpress Grid in my application.
Grid view expects queryable source, so I don't want to use ToList() or AsEnumerable(loads all the data into app memory).
When I use AsQueryable I'm getting LINQ to Entities does not recognize the method...
Query details:
One of the column(Definition) in the table is stored as JSON string. I understand that it is trying to find SQL equivalent for Deserialize method, Please suggest if you know any alternatives..
Below is the query.
var requestList = (from request in db.request_def
let requestDefinition=new JavaScriptSerializer().Deserialize(request.Definition,typeof(RequestInfo))
let user = db.Users.FirstOrDefault(p => p.PRINCIPAL == requestDefinition.Principal)
let processingAccount =user.EMAIL
select new RequestModel
{
CreatedBy = request.CreatedBy
CreatedOn = request.CreateOn,
Status = request.Status,
ProcessingAccount = processingAccount,
}).OrderByDescending(p => p.CreatedOn).AsQueryable<RequestModel>();
You seem to be storing a JSON string in your database but you still want to "join" it to another table. Your options are probably limited to one of the following:
Drag the entire table into memory, deserialise and do your JOIN there. This would likely be horribly slow - don''t do this.
Move to a data store that is designed to be queried like this (i.e. MongodDB, DocumentDB etc.)
When you insert the JSON into your table, copy the value (i.e. Principal) into it's own column so you can do a classic SQL join, materialise the data in your code and then deserialise it.
If you are running SQL Server 2016 or newer then you should be able to run a raw SQL query against the database using SQL Server JSON query
Exclude the ProcessingAccount field from the query to be able to execute it on the server side and retrieve data. Add the Definition field to the RequestModel, instead. Then, add an unbound column in which you will manually load the ProcessingAccount data.
To do this, handle the CustomUnboundColumnData event. In the event handler, obtain the Definition of the current record using the ASPxGridColumnDataEventArgs.GetListSourceFieldValue method, deserialise it, and load User from the database to obtain the ProcessingAccount.
To reduce the amount of database queries, it is better to retrieve Definition value of all records in the current page and load all related Users in batch. You can do this on the first call of the CustomUnboundColumnData event handler, and store the result in a local variable to use it on subsequent calls.
Related
We have a 4 column data grid display on a page. I would like to perform a query based on each of the values within each cell of the grid i.e. 4 queries for each row.
This is so I can populate the cell with count of records in db that matches that value.
When each row gets populated by jqgrid, it fires off an ajax call for each cell.
I think it's a very bad idea since I have already discovered the browser limits the number of ajax calls to the same server.
Are there similar limits for ado.net?
I would like to batch these queries together so I do fewer calls to the db, is this what you would do?
How would you approach this?
You could combine your AJAX calls into one, the resulting object contains an array, or multiple properties for each result set, and then you run your SQL in parallel on the server.
Check out this QA for how to use options on how to use TPL and SQL.
Parallel.Foreach SQL querying sometimes results in Connection
me would suggest you to select the associated id data in the first request and populate the values in the UI.
You could either use join or left join in your first query based on your requirement and architecture and fetch the specific column value/ count(id) ( Here you mentioned as the count of records ).
I am using OData to get records, but due to some performance issues we are having when using the SQL it generates via LINQ, we have decided to write a stored procedure to get the data (using SQL Server as our database). I know how to call the stored procedure and map the result to an entity. The thing I am confused about is when I get an $inlinecount=allpages parameter, how do I manually set the odata.count parameter instead of having OData try to do it?
I'd like to call my stored procedure, which takes in all the filters and sorts, as well as skip and top for paging, as parameters, to get the data. The problem is, I need the total count (without applying the skip/top/sorts) for the odata.count property that should be returned in the response. To even get this count, I would have to either make a second stored procedure that only takes the filters and returns a count, or possibly modify the original one to return a count as an output parameter, along with the data. Regardless, once I get that number, what do I do with it? How do I tell OData to use that as the returned odata.count property, instead of trying to apply its own magic to do so?
If you profile the db when entity framework generates the query, it executes two queries. One for the total count and another for the data. Like you say, it is a similar query, just getting the count instead of the actual data.
As far as how to return it, I have done so in the past using a PageResult<T> - this has a structure to include the count.
You should also consider how you will handle other odata query options, like select. Or, you can disable options that you don't support.
I am developing an HRM application to import and export xml data from database. The application receives exported xml data for the employee entry. I imported the xml file using linq to xml, where I converted the xml into respective objects. Then I want to attach (update) the employee objects.
I tried to use
//linqoper class for importing xml data and converts into IEnumerable employees object.
var emp = linqoper.importxml(filename.xml);
Using (EmployeedataContext db = new EmployeedatContext){
db.attachAllonSubmit(emp);
db.submitchange();
}
But I got error
“An entity can only be attached as modified without original state if it declares as version member or doesn't have an update check policy”.
I have also an option to retrieve each employee, and assign value to the new employee from xml data using this format.
//import IEnumerable of Employee objects
var employees = = linqoper.importxml(filename.xml)
using(Employeedatacontext db = new Employeedatacontext){
foreach(var empobj in employees)
{
Employee emp = db.Employee.where(m=>m.id==empobj.Id);
emp.FirstName=empobj.FirstName;
emp.BirthDate=empobj.BirthDate;
//….continue
}
db.submitChanges();
}
But the problem with the above is I have to iterate through the whole employee objects, which is very tiresome.
So is there any other way, I could attach (update) the employee entity in the database using LINQ to SQL.
I have seen some similar links on SO, but none of them seems to help.
https://stackoverflow.com/questions/898267/linq-to-sql-attach-refresh-entity-object
When linq-to-sql saves the changes to the database, it has to know properties of the object has been changed. It also checks if a potentially conflicting update to the database have been done during the update (optimistic concurrency).
To handle those cases LINQ-to-SQL needs two copies of the object when attaching. One with the original values (as present in the DB) and one with the new, changed values. There is also a more advanced mechanism involving a version member which is mapped to a rowversion column.
The linq-to-sql way to update a set of data is to first read all data from the database, then update the objects retrieved form the database and finally call SubmitChanges(). That would be my first approach in your situation.
If you experience performance problems, then it's time to go outside of linq-to-sql's toolbox. A solution with better performance is to load the new data into a separate staging table (for best performance, use bulk insert). Then run a SQL command or Stored Procedure that does the actual merging of data. The SQL Merge clause is excellent for this kind of updates.
LINQ to SQL is proper ORM, but if you want to take control of create/update/delete in your hand; than you can try some simple ORMs which just provide ways to do CRUD operations. I can recommend one http://crystalmapper.codeplex.com, it is simple yet powerful.
Why CrystalMapper?
I built this for large financial transaction system with lots of insert and update operations. What I need is speed and control of insert/update serving complex business scenarios ... hitting multiple tables just for one transaction.
When I put this to use in social text processing platform, it serves very well there too.
I have a multi-page (multi-view) form in MVC, the results of which will be saved to a single database table.
Code snippet that initializes the linq object in the first page of the form.
public ActionResult MyForm()
{
// returns a Linq object stored in session
Application currentApp = Application.FromSession();
// if null, initialize the object and save to session
if (currentApp == null)
{
currentApp = new Application();
currentApp.SessionSave();
}
return View(currentApp);
}
And here is a sample snippet of code for the final action that updates some data from the strongly-typed model, then triggers the database save.
[HttpPost]
public ActionResult MyForm3(Application app, FormCollection coll)
{
Application currentApp = Application.FromSession();
currentApp.Contact = app.Contact;
currentApp.AddFormToXml(coll);
currentApp.SessionSave();
_db.Applications.InsertOnSubmit(currentApp);
_db.SubmitChanges();
return RedirectToAction("Blah");
}
The problem I'm running into is that the SubmitChanges fails with the error
Cannot insert the value NULL into
column 'ApplicationData', table
'MyTable';
column does not allow nulls. INSERT
fails. The statement has been
terminated.
In this case, ApplicationData is a column of type xml, which LINQ interprets as an XElement object. When I set a breakpoint at SubmitChanges() and check the value of app.ApplicationData, it is clearly populated (non-null), and yet I continue to get this error. My only thought is that I am misunderstanding something with how data contexts work. It only seems to have an issue with this one column though. Is it possible that I need to figure out a way to attach the XElement object (ApplicationData) to my active data context (_db), and if so, how would I go about doing that?
Take a look at the actual SQL generated and sent to the server.
Start up SQL Server Profiler (on the tools menu in SQL Server Management Studio) and start a trace. Run your application until it crashes. Go back to SQL profiler and look at the SQL queries. Seeing things from the SQL end sometimes make it easy to spot the error, e.g. finding out if your are doing several inserts instead of just one.
Well my suggestion to you is to compare the data type of "ApplicationData" column in your Context model and in your database table.
Also please check your LINQ to SQL mappings for this column "AppliationData" again on the datatype itself.
Please update your post if you find anything...
Ok, so in the action method you mentioned can you check if you are calling the InsertOnSumbit Method again anywhere else before you are finally calling db.SubmitChanges()...or if you are calling the InsertOnSubmit method more than once... I think that will cause a problem if you are calling it twice on the same object.
Update:
I did tried a sample with a single table and was able to insert the xml data as mentioned below.
DataClassesDataContext ctx = new DataClassesDataContext();
Application a1 = new Application();
XName n = "dfdsf";
a1.ApplicationData = new XElement(n);
ctx.Applications.InsertOnSubmit(a1);
ctx.SubmitChanges();
so, now the question will be what does your column data looks like??? if you can post the sample content of the application data then it will be helpful. Also how are you setting the ApplicationData property value?
Is there a way to program the following SQL query
SELECT dbo.Assets_Master.Serial_Number, dbo.Assets_Master.Account_Ident, dbo.Assets_Master.Disposition_Ident
FROM dbo.Assets_Master LEFT OUTER JOIN
dbo.Assets ON dbo.Assets_Master.Serial_Number = dbo.Assets.Serial_Number
WHERE (dbo.Assets.Serial_Number IS NULL)
in c# .net code using dataviews or data relation or something else?
I have a spreadsheet of about 4k rows and a data table that should have the same records but if not I want to display the missing (non-matching) records from the table.
Thanks,
Eric
If you've already got that query, you can just pass that text as a SQL command and pull back the results as a dataset. Better might be setting up your query as a stored procedure and then following the same steps (calling a stored proc is cleaner than writing the SQL by hand).
If you want a way to do it without SQL at all, you could use LINQ to grab an IENUMERABLE of your ASSETS_MASTER serial numbers and another IENUMBERABLE of your ASSETS records. Then something like:
foreach(ASSET asset in ASSETS)
{
if(!ASSETS_MASTER_SERIALSNOS.CONTAINS(asset.SerialNumber))
{
//Do Whatever
}
}