Below Code works fine.
public static void UpdateCategory(Category category) {
var dbFactory = new OrmLiteConnectionFactory(connString, SqlServerDialect.Provider);
using (IDbConnection db = dbFactory.OpenDbConnection()) {
try{
db.Update<Category>(category);
}
catch (Exception e) {
throw new Exception(string.Format("Error within {0}", e.Message));
}
}
}
Below code does not?
public static int UpdateRowInTable<T>(object value) {
var dbFactory = new OrmLiteConnectionFactory(connString, SqlServerDialect.Provider);
using (IDbConnection db = dbFactory.OpenDbConnection()) {
try {
result = db.Update<T>(value);
}
catch (Exception e) {
throw new Exception(string.Format("Error within {0}", e.Message));
}
}
}
thanks
Related
I have a wcf api and wish to wrap all requests inside a transaction
Currently my code looks like this in each endpoint
public MyCompleteList ReadOrganisations()
{
MyCompleteList resp = new MyCompleteList ();
try
{
using (TransactionScope scope = new TransactionScope())
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
DC_Base browser_request = new DC_Base(PROJECT);
browser_request.cmd_user_id = coreDb.GetUserIDFromLoginName(PROJECT,
HttpContext.Current.User.Identity.Name);
resp =
new MyCompleteList (coreSc.User_Read_All_Organisations(browser_request, utils,
validation, coreSc, coreDb));
scope.Complete();
}
else
{
resp.SetResponseNotLoggedIn();
}
}
}
catch (TransactionAbortedException ex)
{
resp.SetResponseServerError();
}
catch (ApplicationException ex)
{
resp.SetResponseServerError();
}
return resp;
}
As you can see if I am to use the "using" transaction scope part in every endpoint (approx 300) its going to be a lot of duplicated code.
is there anyway to reduce the amount of duplication?
You can write a helper method, that handles the transaction logic while calling your actual code as a lambda.
public static T Execute<T>(Func<T> func, TransactionExecutionOptions options = null)
{
options = options ?? TransactionExecutionOptions.Default;
T res;
using (var tx = new TransactionScope(options))
{
res = func();
tx.Complete();
}
return res;
}
Depending on your needs you can provide additional arguments to the Func argument; for example, the Execute method could also open a database connection and pass that to the func (then having Func<IDbConnection, T> as parameter type). YMMV.
For your example:
public MyCompleteList ReadOrganisations()
{
MyCompleteList resp = new MyCompleteList ();
try
{
resp = Execute(() => {
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
DC_Base browser_request = new DC_Base(PROJECT);
browser_request.cmd_user_id = coreDb.GetUserIDFromLoginName(PROJECT,
HttpContext.Current.User.Identity.Name);
resp =
new MyCompleteList (coreSc.User_Read_All_Organisations(browser_request, utils,
validation, coreSc, coreDb));
scope.Complete();
}
else
{
resp.SetResponseNotLoggedIn();
}
});
}
catch (TransactionAbortedException ex)
{
resp.SetResponseServerError();
}
catch (ApplicationException ex)
{
resp.SetResponseServerError();
}
return resp;
}
If possible, you can also factor the SetResponse*() methods out into a base class or interface (say IMyResponse), thus making it possible to handle this aspect inside the Execute method as well.
public static T Execute<T>(Func<T> func, TransactionExecutionOptions options = null) where T : IMyResponse
{
options = options ?? TransactionExecutionOptions.Default;
T res;
try
{
using (var tx = new TransactionScope(options))
{
res = func();
tx.Complete();
}
}
catch (TransactionAbortedException ex)
{
res.SetResponseServerError();
}
catch (ApplicationException ex)
{
res.SetResponseServerError();
}
return res;
}
1- Create a ServiceBase class as follows
public class ServiceBase
{
protected void ExecuteOperation(Action codetoExecute)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
codetoExecute.Invoke();
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
// handle exception
}
catch (ApplicationException ex)
{
// handle exception
}
}
}
2- Each new service must inherits from ServiceBase and call ExecuteOperation instead. Code as follows:
ExecuteOperation(() =>
{
// Custom code here
});
3- Atomic transactions are useful when executing operations that dont expect results in return.
public async Task<ActionResult> Index()
{
var service = new CoreServiceFactory().GetImpersonatingService();
try
{
var data = new Impersonation()
{
ImpersonatingId = "dac733c3-01ad-447b-b0df-3a7c21fef90b",
UserId = "dac733c3-01ad-447b-b0df-3a7c21fef90b"
};
var imp = await service.Add(data);
}catch(Exception ex) { throw ex; }
return View();
}
Above is one of my controllers action method. And this works fine when the insertion is successful. This should fail if the data already exists in database(unique constraints). So when i intentionally try to make it fail(i manually add the same record in the db and then try to add it again via this action method) the action method goes into a loop or something, the exception is never thrown , chrome keeps me showing me the loading icon , looks like it went into some deadlock state. Can someone please help me understand why it goes into deadlock state when exception is thrown and how can i handle it?
Below are the reference methods
service.Add(data)
public async Task<Impersonation> Add(Impersonation t)
{
if (ValidateData(t))
{
using (var uow = GetUnitOfWork())
{
var r = GetRepository(uow);
var item = r.Add(t);
try
{
var ret = await uow.Save();
if (ret > 0)
{
return item;
}
else
{
return null;
}
}
catch (Exception ex)
{
throw ex;
}
}
}
else
{
throw new ValidationException(null, "error");
}
}
uow.Save()
public class BaseUnitOfWork : IUnitOfWork
{
public DbContext _Context { get; private set; }
public BaseUnitOfWork(DbContext context)
{
this._Context = context;
}
public async Task<int> Save()
{
try
{
var ret = await this._Context.SaveChangesAsync();
return ret;
}catch(Exception ex)
{
throw ex;
}
}
}
Here is my suggestion: in uow.Save, log the error in the catch block and return zero (do not throw any exceptions).
public class BaseUnitOfWork : IUnitOfWork
{
public DbContext _Context { get; private set; }
public BaseUnitOfWork(DbContext context)
{
this._Context = context;
}
public async Task<int> Save()
{
try
{
var ret = await this._Context.SaveChangesAsync();
return ret;
}catch(Exception ex)
{
// log the error here
return 0;
}
}
}
I'm not sure if returning the null in the Add service is a good idea or not, you might need to handle that differently too.
I have created a database in mongodb using asp.net mvc but when i look to my database the insertion is failed .I have tested before in a console application and it works correctly but now I don't find the problem when i use mvc!can you help me please
this is my code
//IDeviseRepository
namespace WebApplication6
{
public interface IDeviseRepository
{
Devise Add(Devise devise);
void MongoGoNow();
}
}
//DeviseRepository
namespace WebApplication6
{
public class DeviseRepository : IDeviseRepository
{
public IMongoDatabase db;
public DeviseRepository()
{
MongoClientSettings settings = new MongoClientSettings();
settings.Server = new MongoServerAddress("localhost", 27017);
MongoClient client = new MongoClient(settings);
this.db = client.GetDatabase("bigdata");
var collection = db.GetCollection<Devise>("Devise");
}
public IMongoCollection<Devise> Devise
{
get
{ return db.GetCollection<Devise>("Devise"); }
}
public Devise Add(Devise devise)
{
var collection = db.GetCollection<Devise>("Devise");
collection.InsertOne(devise);
return devise;
}
public void MongoGoNow()
{
var collection = db.GetCollection<Devise>("devise");
var result = TestFind(collection);
result.GetAwaiter().GetResult();
}
static async Task TestFind(IMongoCollection<Devise> MyCollection)
{
var filter = new BsonDocument();
var count = 0;
using (var cursor = await MyCollection.FindAsync(filter))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var document in batch)
{
count++;
}
}
}
}
public void insertdata()
{
var devise = new Devise();
devise.parité = "euro/dollar";
Devise.InsertOne(devise);
}
}
}
Try updating your insert to:
public void insertdata()
{
try
{
var devise = new Devise();
devise.parité = "euro/dollar";
Devise.InsertOne(devise);
}
catch (Exception ex)
{
//put a breakpoint here
}
}
I have an android application which receives registered IDs and sends GCM. When a device registers I would like to take its id and add it to my MSSQL server. How can I get the devices's registered ID with asp.net?
android request code:
private void sendRegistrationIdToBackend() {//Sunucuya regid deðerini gönderecek method
URI url = null;
try {
url = new URI("http://aaaaa.com/bbbbb/duyuru-haber.aspx?regId=" + regid);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(url);
try {
httpclient.execute(request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
asp.net get ıd code :
string registered_id = Request.QueryString["regId"];
Try the following code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch);
context = getApplicationContext();
if (checkPlayServices())
{
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty())
{
registerInBackground();
}
else
{
Log.d(TAG, "No valid Google Play Services APK found.");
}
}
}
private String getRegistrationId(Context context)
{
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.d(TAG, "Registration ID not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.d(TAG, "App version changed.");
return "";
}
return registrationId;
}
private SharedPreferences getGCMPreferences(Context context)
{
return getSharedPreferences(LaunchActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
private static int getAppVersion(Context context)
{
try
{
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
}
catch (NameNotFoundException e)
{
throw new RuntimeException("Could not get package name: " + e);
}
}
private void registerInBackground()
{ new AsyncTask() {
Override
protected Object doInBackground(Object... params)
{
String msg = "";
try
{
if (gcm == null)
{
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: "+msg);
}
catch (IOException ex)
{
msg = "Error :" + ex.getMessage();
}
return null;
} protected void onPostExecute(Object result)
{ //to do here };
}.execute(null, null, null);
}
You may want to make sure you added all the required lines in the AndroidManifest file, as well as declaring a GCM Service and a GCM Broadcast Receiver.
Link to the full answer
I have SVC services running in the Asp.net hosted with IIS 7.5, When the exception occurs it is not throwing the exception and continues to execute the next line!
I am specificaly throwing the error as below when condition not met or for example data not found.
throw new Exception("Data Not Found");
My code is as below
using System;
public class DataProvider : IDataProvider
{
private AccountData _accountData;
private OwnerData _ownerData;
public DataProvider()
{
var dataAccessor = new DataAccessor();
_accountData = dataAccessor.AccountDetails();
//throw the error in constructor
if (_accountData == null)
throw new Exception("Data Not Found");
if (_accountData.AccountInfo != null)
{
_ownerData = _accountData.AccountInfo.OwnerData;
//continue....
}
}
public string GetAccountOwner()
{
if (_ownerData != null)
{
return _ownerData.Name;
}
return null;
}
}
Main Method:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class AccountService : IAccountService
{
private readonly IDataProvider _dataProvider;
public AccountService()
: this(new DataProvider())
{
}
public AccountService(IDataProvider dataProvider)
{
_dataProvider;= dataProvider;
}
public AccountResponse GetOwner()
{
try
{
var owner = _dataProvider.GetAccountOwner();
return new AccountResponse
{
Owner = owner
};
}
catch (Exception ex)
{
if (ex.Message == "Data Not Found")
{
//do something here...
}
return null;
}
}
}