Handling Errors with db.Database.SqlQuery - entity-framework

I came across an issue today where I had a query that was failing. I am using db.Database.SqlQuery<T>() to query another applications data. We have a custom view over their data. Today the admin rebuilt the indexes in the software and in the process deleted the custom view. While that is an issue that SO can't solve, the issue you can help with is gracefully handling the case where the view no longer exists.
For the main application, we are using this data as supplemental data. Meaning that it isn't critical to have the information display if the server or table can't be reached. The query is run in the follow WebApi action (I added a few comments based on my observations while debugging.):
public Task<HttpResponseMessage> GetByAddress(string id)
{
Task<HttpResponseMessage> response;
string sql = // my sql statement;
List<object> parameterList = new List<object>();
parameterList.Add(id.ToUpper());
object[] param = parameterList.ToArray();
// This is worthless since the following line will completely replace this
IEnumerable<CallsForService> calls = new List<CallsForService>();
// If the table does not exist, this does not throw an error, instead it creates a different object with the error details.
calls = db.Database.SqlQuery<CallsForService>(sql, param);
response = Task.FromResult<HttpResponseMessage>(Request.CreateResponse(HttpStatusCode.OK, calls));
return response;
}
My question then is how do I check for these errors and at least gracefully send back to the calling application an empty list. I can then log these errors with ELMAH so I can catch the issue and get it fixed.

The query is not executed until the results are enumerated, so you can just count the number of records returned and make it raise an error if there any.
calls = db.Database.SqlQuery<CallsForService>(sql, param);
var recCount = calls.Count();
Any errors raised after the last line will be caught by the try/catch block.

Related

SAPUI5 batch submit returns error

I am using the following code, in an attempt to batch upload the changes made on a table:
onConfirmActionPressed: function() {
var oModel = this.getModel();
oModel.setUseBatch(true);
oModel.submitChanges();
}
I am using setProperty() to set the new values, like this:
onSingleSwitchChange: function(oControlEvent) {
var oModel = this.getView().getModel();
var rowBindingContext = oControlEvent.getSource().getBindingContext();
oModel.setProperty(rowBindingContext.sPath + "/Zlspr", "A");
}
When onConfirmActionPressed is executed, I get a server error, saying that "Commit work during changeset processing not allowed" on SAP R3.
When I upload the lines of the table one-by-one, it works fine. However, uploading this way is very slow, and in some cases it takes more than 10 minutes for the process to complete.
Am I doing something wrong while batch submitting? Is there a chance the issue is due to server (R3) misconfiguration?
You need to override methods:
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END
Keep track of the errors across all calls to update methods and if everything went OK then in changeset_end perform commit on the database
edit:
To clarify:
In your Data Provider Class Extension in SAP Gateway you need to find your YOURENTITY_UPDATE_ENTITY method and get rid off any COMMIT WORK statements.
Then you need to redefine /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN method and, which is a method which is fired before any batch operation. You could define a class attribute such as table mt_batch_errors which would be emptied in this method.
When you post batch changes from UI5 using oModel.submitChanges() all single changes to Entities are directed to appropriate ..._UPDATE_ENTITY methods. You need to keep track of any possible errors and if any occurs then fill your mt_batch_errors table.
After all entities have been updated /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END method is fired in which you are able to check mt_batch_errors table if any errors occurred during the batch process. If there were errors then you should probably ROLLBACK WORK, and if not then you are free to COMMIT WORK.
That is just an example of how it could be done, I'm curious of other suggestions.
Good luck!

Add single record to mongo collection with meteor

I am a new user to JavaScript and the meteor framework trying to understand the basic concepts. First of all I want to add a single document to a collection without duplicate entries.
this.addRole = function(roleName){
console.log(MongoRoles.find({name: roleName}).count());
if(!MongoRoles.find({name: roleName}).count())
MongoRoles.insert({name: roleName});
}
This code is called on the server as well as on the client. The log message on the client tells me there are no entries in the collection. Even if I refresh the page several times.
On the server duplicate entries get entered into the collection. I don't know why. Probably I did not understand the key concept. Could someone point it out to me, please?
Edit-1:
No, autopublish and insecure are not installed anymore. But I already published the MongoRoles collection (server side) and subscribed to it (client side). Furthermore I created a allow rule for inserts (client side).
Edit-2:
Thanks a lot for showing me the meteor method way but I want to get the point doing it without server side only methods involved. Let us say for academic purposes. ;-)
Just wrote a small example:
Client:
Posts = new Mongo.Collection("posts");
Posts.insert({title: "title-1"});
console.log(Posts.find().count());
Server:
Posts = new Mongo.Collection("posts");
Meteor.publish(null, function () {
return Posts.find()
})
Posts.allow({
insert: function(){return true}
})
If I check the server database via 'meteor mongo' it tells me every insert of my client code is saved there.
The log on the client tells me '1 count' every time I refresh the page. But I expected both the same. What am I doing wrong?
Edit-3:
I am back on my original role example (sorry for that). Just thought I got the point but I am still clueless. If I check the variable 'roleCount', 0 is responded all the time. How can I load the correct value into my variable? What is the best way to check if a document exists before the insertion into a collection? Guess the .find() is asynchronous as well? If so, how can I do it synchronous? If I got it right I have to wait for the value (synchronous) because I really relay on it.
Shared environment (client and server):
Roles = new Mongo.Collection("jaqua_roles");
Roles.allow({
insert: function(){return true}
})
var Role = function(){
this.addRole = function(roleName){
var roleCount = Roles.find({name: roleName}).count();
console.log(roleCount);
if(roleCount === 0){
Roles.insert({name: roleName}, function(error, result){
try{
console.log("Success: " + result);
var roleCount = Roles.find({name: roleName}).count();
console.log(roleCount);
} catch(error){
}
});
}
};
this.deleteRole = function(){
};
}
role = new Role();
role.addRole('test-role');
Server only:
Meteor.publish(null, function () {
return Roles.find()
})
Meteor's insert/update/remove methods (client-side) are not a great idea to use. Too many potential security pitfalls, and it takes a lot of thought and time to really patch up any holes. Further reading here.
I'm also wondering where you're calling addRole from. Assuming it's being triggered from client-side only, I would do this:
Client-side Code:
this.addRole = function(roleName){
var roleCount = MongoRoles.find({name: roleName}).count();
console.log(roleCount);
if (roleCount === 0) {
Meteor.call('insertRole', roleName, function (error, result) {
if (error) {
// check error.error and error.reason (if I'm remembering right)
} else {
// Success!
}
});
}
}
How I've modified this code and why:
I made a roleCount variable so that you can avoid calling MongoRoles.find() twice like that, which is inefficient and consumes unneeded resources (CPU, disk I/O, etc). Store it once, then reference the variable instead, much better.
When checking numbers, try to avoid doing things like if (!count). Using if (count === 0) is clearer, and shows that you're referencing a number. Statements like if (!xyz) would make one think this is a boolean (true/false) value.
Always use === in JavaScript, unless you want to intentionally do a loose equality operation. Read more on this.
Always use open/closed curly braces for if and other blocks, even if it contains just a single line of code. This is just good practice so that if you decide to add another line later, you don't have to then wrap it in braces. Just a good practice thing.
Changed your database insert into a Meteor method (see below).
Side note: I've used JavaScript (ES5), but since you're new to JavaScript, I think you should jump right into ES6. ES is short for ECMAScript (which is what JS is based on). ES6 (or ECMAScript 2015) is the most recent stable version which includes all kinds of new awesomeness that JavaScript didn't previously have.
Server-side Code:
Meteor.method('insertRole', function (roleName) {
check(roleName, String);
try {
// Any security checks, such as logged-in user, validating roleName, etc
MongoRoles.insert({name: roleName});
} catch (error) {
// error handling. just throw an error from here and handle it on client
if (badThing) {
throw new Meteor.Error('bad-thing', 'A bad thing happened.');
}
}
});
Hope this helps. This is all off the top of my head with no testing at all. But it should give you a better idea of an improved structure when it comes to database operations.
Addressing your edits
Your code looks good, except a couple issues:
You're defining Posts twice, don't do that. Make a file, for example, /lib/collections/posts.js and put the declaration and instantiation of Mongo.Collection in there. Then it will be executed on both client and server.
Your console.log would probably return an error, or zero, because Posts.insert is asynchronous on the client side. Try the below instead:
.
Posts.insert({title: "title-1"}, function (error, result) {
console.log(Posts.find().count());
});

breezejs navigation property with include not working

I have server side code written which is including navigational property for many to many relation ship as shown below.
var result = _contextProvider.Context.ResourceProperty.Include("AssociatedStandardResourceProperty.AssociatedLists").Where(t => t.ResourceId == resId);
//Return matching resource properties
return result;
However, when i am trying to retrieve data from breeze datacontext i am getting query execution error as shown below.
var getResourceProperties = function (resourceId, resourcePropertyObservable) {
var query = EntityQuery.from('GetResourceProperties')
.withParameters({ resourceId: resourceId })
.expand("AssociatedStandardResourceProperty.AssociatedLists");
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (resourcePropertyObservable) {
resourcePropertyObservable(data.results);
}
log('Retrieved listObservable from remote data source',
data, true);
}
};
Query is failing and all data is retreived in log message i have written in queryFailed function.
I have also checked by removing expand at client side and also removing include at server side and then including expand at client side.
Please let me know how i can make it work.
Thanks
I have observed that problem was due to many to many mapping between two entities . After removing the relationship we are able to retrieve associatedEntities data
Just a guess here, but if you are performing the include on the server, then you don't need the expand on the client and vice versa. Your example seems to be doing both. What is the error message that you are getting?

Entity Framework 4.0 - The underlying provider failed on Open

We have a web application with Entity Framework 4.0. Unfortunately, when the large volume of users hit the application the EF throws an error
The underlying provider failed on Open
Below is the code snippet:
//DAL
public IQueryable<EmployeeEntity> GetEmployeeDetail()
{
DatabaseEntities ent = new DatabaseEntities(this._connectionString);
IQueryable<EmployeeEntity> result = from employee in ent.EmployeeEntity
select employee;
return result;
}
Please note the above code returns IQuerable.
Is anything wrong with above pattern that could cause the exception to occur?
When and how does Entity Framework determine to close / open db connection and also how long to retain?
On what scenario does above error occurs?
What's the maximum number of connection pool for EF and how do we configure?
Do we need to explicitely specify open and close
Is code below a best way to resolve above issue?
public IQueryable<EmployeeEntity> GetEmployeeDetail()
{
using (DatabaseEntities ent = new DatabaseEntities(this._connectionString))
{
IQueryable<EmployeeEntity> result = from employee in ent.EmployeeEntity
select employee;
return result.ToList().AsQuerable();
}
}
The ToList() call will cause the query to run on the database immediately and as this is not filtered in any way will return every employee in your database. This is probably likely to cause you performance issues.
However you can't remove this in your case because if you return the IQueryable directly then the context will be disposed by the time you try and fetch results.
You could either:
change the way it works so that the scope of ent does not end when the method returns and return the query without calling ToList(). You can then further filter the IQueryable before calling ToList().
call ToList() within the method but filter/limit the query first (e.g. pass some parameters into the method to specify this) to reduce the number of rows coming back from the database.

cannot open user default database. login failed error

I am getting this "cannot open user default database. login failed" error. What I did was using ORM to create DataContext, in the code first call TableExists function to check if the version_tbl existed, if not, then call scripts to exec sql commands to create version_tbl. Then create a new dataContext, but problem is after the call I am getting this error on dataContext entity. If I remove the TableExists call, then dataContext creation is fine or move the dataContext creation before the TableExists call, but then the problem occurs in the TableExists call when it tries to connect. Seems like I can only connect once. Anyway I can call TableExists then able to create dataContext?
Below is my code sample
static bool TableExists(string tableName)
{
using (SqlConnection connection = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=planning;Integrated Security=True"))
{
string checkTable =
String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'",
tableName);
SqlCommand command = new SqlCommand(checkTable, connection);
command.CommandType = CommandType.Text;
connection.Open();
bool retVal = Convert.ToBoolean(command.ExecuteScalar());
return retVal;
}
}
myFunc ()
{
if (!TableExists ("version_tbl"))
{
// call scripts to create version_tbl
}
DataContext ctx = new DataContext ();
Before everything else did you check if your domain user has the appropriate DB rgihts?
Try to validate the DB connection first.
You should be able to open two connections to the database at the same time: 1 through ADO.NET and 1 through LinqToSql.
The format of your code as displayed by StackOverflow is difficult to read, but it appears that you are returning from your TableExists method before the using statement is able to close the connection. Does it make any difference if you change that?
Are you getting different errors depending on which order you open the connections or is it always the same error?
Don't stop with the Exception. Go to the database and check the message in the log. The exceptions for LOGIN's are not clear on purpose for security reasons, but the log should have a better explanation of what happened.