Entity Framework Connection error event - c#

I'm trying to catch all SQLExceptions (connection error, timeout, etc) that EF might throw in a single place. I'm using a unit of work pattern with DI so there's no var using = context for example. Calls like .Single or .ToList are used all around the business logic.
Is there any hook or event of class I could overwrite or inject to do this?

Assuming your Unit of Work eventually calls DbContext.SaveChanges(), you can wrap this call with a try-catch.
Another option, which requires some discipline from your development team, is to add two methods in a base BL class: IList<T> MaterializeList<T>(IQueriable<T> query) and T MaterializeSingle<T>(IQueriable<t> query), which will look something like this:
protected IList<T> MaterializeList<T>(IQueriable<T> query) {
try {
return query.ToList();
}
catch {
//your error handling code here
}
}
and
protected T MaterializeSingle<T>(IQueriable<t> query) {
try {
return query.FirstOrDefault();
}
catch {
//your error handling code here
}
}
and then always materialize using these methods.
As a side note, I try to keep my LINQ to Entities queries in my Data Access layer, leaving the Business Logic layer ignorant of the data access technology.

Little bit work to do, but this will help you i think:
Encapsulate you DbContext withing a fake-context and hide your DbSets. You build an new context which will be the context for you business-logic. This one doesn't give access to the DbSets, it shows custom-dbSets to the user. The main work will be to build the fake-context, which needs to have all methods you're using on the real dbSets.
/// <summary>
/// This sould no be used anywhere except in MyDbContext2
/// </summary>
public class MyDbContext : DbContext
{
public DbSet<SomeTableClass> SomeTable { get; set; }
}
/// <summary>
/// This will be your context in the business-logic
/// </summary>
public class MyDbContext2
{
private MyDbContext realDb;
public MyDbContext2(string conStr)
{
realDb = new MyDbContext();
}
public MyDbSet<SomeTableClass> SomeFakeTable { get; set; }
}
/// <summary>
/// Fake-set with logging
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyDbSet<T> where T : class
{
private DbSet<T> dbSet;
public MyDbSet(DbSet<T> realDbSet)
{
this.dbSet = realDbSet;
}
public List<T> ToList()
{
try
{
return dbSet.ToList();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
public T SingleOrDefault()
{
try
{
return dbSet.SingleOrDefault();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
}
A good idea would be to rename you DbContext and introduce a the fake-one with the old name. This way Visual Studio will show you which methods you have to implement.

Related

How to get current transaction in ASP.NET Boilerplate?

I have a project that written ASP.NET Boilerplate (assembly version=4.0.2.0).
I want get current transcation object in Application layer. How can I achieve this?
You get current unit of work with using IUnitOfWorkManager.
IUnitOfWorkManager _unitorWorkManager;
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
_unitOfWorkManager.Current//gives you current unit of work
.SaveChanges();//same thing with transaction.Commit();
}
If your class inherits something like AbpController, BackgroundJob, AbpServiceBase etc..., you can also use CurrentUnitOfWork.
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
CurrentUnitOfWork.SaveChanges();//same thing with transaction.Commit();
}
You can check https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work for more information.
Edit: I guess it is not possible to get it in application layer directly since it need dbcontext parameter. What about creating a domain service which provides ActiveDbTransaction. You can create an interface for that in *.Core project and define it where you can access to dbcontext
public interface IMyDbContextActiveTransactionProvider
{
/// <summary>
/// Gets the active transaction or null if current UOW is not transactional.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args);
}
Implement it someplace you can access to dbcontext
public class MyDbContextActiveTransactionProvider: IMyDbContextActiveTransactionProvider, ITransientDependency {
private readonly IActiveTransactionProvider _transactionProvider;
public MyDbContextActiveTransactionProvider(IActiveTransactionProvider transactionProvider){
_transactionProvider = transactionProvider;
}
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args){
return _transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(MyDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
}
https://aspnetboilerplate.com/Pages/Documents/Articles/Using-Stored-Procedures,-User-Defined-Functions-and-Views/index.html#DocHelperMethods

Memory leak when using Entity Framework

I have a very simple application using EF. But when it runs a week, the memory usage is awful (only 80MB at first, 700MB after one week).
When I use dotMemory to profile my application. I find the memory of Heap generation 2 is increasing all the time.
I Get a snapshot, finally find the retained bytes of ef dbcontext is the most.
I am so confused. My application is so simple. Code sample:
protected CarbonBrushMonitorEntities _entities = new MYEntities();
public void Add(HistoryData data)
{
_entities.HistoryDatas.Add(data);
_entities.SaveChanges();
}
_entities only initials once at the starting time, then used all the time.
The function Add is frequently called,about 3 times/second
I google a long time, and try some methods such as:
_entities.Configuration.ValidateOnSaveEnabled = false;
_entities.Configuration.AutoDetectChangesEnabled = false;
_entities.Configuration.LazyLoadingEnabled = false;
but these do not work.
If you use entity framework, you should create the context just before you need it and dispose it as soon as possible:
using (var someContext = new SomeContext())
{
// your commands/queries
}
Never keep context in memory or share it across different calls.
What I typically do is register the context with an IoC container:
DependencyFactory.RegisterType(typeof(SomeContext));
and use a context resolver (also registered with IoC of course) like:
using (var someContext = _contextResolver.ResolveContext())
{
// your commands/queries
}
where resolution is done like:
public class ContextResolver : IContextResolver
{
public ISomeContext ResolveContext()
{
return DependencyFactory.Resolve<SomeContext>();
}
}
The EF context is actually your unit of work, which should be disposed of once you don't need it anymore.
The other way is to clear the changetracker of the respective entities of concern or even
of all the entities. This is done by changing the entity state to "Detached". This called after dbContext.SaveChangesAsync()
protected void DisposeDbset<T>() where T : class
{
var Tname = typeof(T).Name;
var changetrackercollection = _unitOfWork.dbContext.ChangeTracker.Entries<T>();
foreach (var item in changetrackercollection.ToList())
{
item.State = EntityState.Detached;
}
GC.Collect();
}
I recently faced a similar situation where I was inserting 3,00,000 rows in batch operation. After inserting the rows, the change tracking info for all the rows remained in the memory with the entity state as Unchanged. Hence after every SaveChangesAsync() call, the changetracker accumulated.
I could not resolve new instance dbcontext for every batch, as it was a more expensive operation.
Just FYI, i had configured dbConetext.ChangeTracker.QueryTrackingBehavior = NoTracking. But this is applicable to while fetching the data.
Hopefully this is helpful. I found my solution with the help of this link http://andreyzavadskiy.com/2016/09/23/entries-in-entity-framework-changetracker-could-degrade-database-write-performance/?unapproved=19301&moderation-hash=4acc61a32ead7232959c2ec1ca268180#comment-19301
Based on Chintan shah answer I made an extension method and an example.
public static class DbContextExtensions
{
/// <summary>
/// Set all entries in ChangeTracker to detached to get them collected by the GC
/// </summary>
/// <param name="context"></param>
public static void DetachAllEntriesInChangeTracker(this DbContext context)
{
try
{
foreach (var entityEntry in context.ChangeTracker.Entries())
{
entityEntry.State = EntityState.Detached;
}
}
catch (Exception e)
{
LogManager.GetLogger(context.GetType().FullName).Error(e, "error when detaching all entries in changeTracker");
}
}
}
public class FooDbContext : DbContext
{
public override void Dispose()
{
this.DetachAllEntriesInChangeTracker();
base.Dispose();
}
}

Reference to an ASMX webservice wants to implement IDisposable

I have a somewhat simple web app, that uses an ASMX web service as its sole data access. All the information is gotten from it, and saved to it. It works fine so thats out of the way.
I just updated to VS2012, and it complained about the class implementing the service reference, does not inherit from IDisposeable.
After some reading, i am more confused as some solutions are really elaborate, some are simple. Short version is, after understanding so little, it seems like i cant adapt it to how my app is made.
I have several data access classes, all focusing on methods for an area. For example, one dataaccess for customer related calls, one for product related calls etc.
But since they are all using the same service, they all derive from a base data access class that holds the reference.
This is the base data access class:
public class BaseDataAccess
{
private dk.odknet.webudv.WebService1 _service;
private string _systemBrugerID, _systemPassword;
public BaseDataAccess()
{
//Gets the system user and password that is stored in the webconfig file. This means you only have to change
//the username and password in one place without having to change the code = its not hardcoded.
_systemBrugerID = System.Configuration.ConfigurationManager.AppSettings["SystemBrugerID"].ToString();
_systemPassword = System.Configuration.ConfigurationManager.AppSettings["SystemPassword"].ToString();
_service = new dk.odknet.webudv.WebService1();
}
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get { return _service; }
}
/// <summary>
/// Gets the system user id, used for certain methods in the webservice.
/// </summary>
protected string SystemBrugerID
{
get { return _systemBrugerID; }
}
/// <summary>
/// Gets the system user password, used for certain methods in the webservice.
/// </summary>
protected string SystemPassword
{
get { return _systemPassword; }
}
}
And here is how a derived class utilizes the service reference from the base class:
public class CustomerDataAccess : BaseDataAccess
{
public CustomerDataAccess() {}
/// <summary>
/// Get's a single customer by their ID, as the type "Kunde".
/// </summary>
/// <param name="userId">The user's username.</param>
/// <param name="customerId">Customer's "fkKundeNr".</param>
/// <returns>Returns a single customer based on their ID, as the type "Kunde".</returns>
public dk.odknet.webudv.Kunde GetCustomerById(string userId, string customerId)
{
try
{
return Service.GetKunde(SystemBrugerID, SystemPassword, userId, customerId);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}}
So how on earth do i implement IDisposable in this situation? I just cant wrap my head around it.
EDIT
I have fiddled with the service reference, and come up with this:
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get
{
try
{
using (_service = new dk.odknet.webudv.WebService1())
{
return _service;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}
Yes the exception handling isnt great, i will get to that (advice is appreciated), but VS2012 does not complain about the lack of IDisposable anymore.
Instantiation of the service has been removed from the constructor. The app works fine without any further modifications.
Will this suffice?

Reporting on code execution and design patterns?

First of all I wanted to thank all of you for your continuous contributions to the Stack Overflow community! I've been a member of Stack Overflow for years and have come to rely on your input more so than any other source online. Though I try to participate and answer members' questions whenever I can, every once in a while I find myself stuck and in need of help.
Speaking of which I have an unusual code problem. I am writing an API library in C# that needs to be able to be called from WPF/Windows Forms application, but also from within Unit Test code.
The issue is that I need to be able to report (in Excel) on whether each method of the library executed properly when the API is called from within a WPF/windows forms application, along some other metadata and optionally a return type.
When the code is consumed within Unit Tests I don't really care about the reporting, but I do need to be able to produce an Assert on whether the API call executed properly or not.
For instance, if in a Unit Test we have an Test Initialize portion, one of the API calls may be to create a Domain User for the test method to use. Another one may also create a Domain Group, so that the user has proper group membership.
To accomodate the consumption of the API from WPF/WinForms, I've been rewriting every function in the API to return a OperationStep type, with the hopes that when all API calls have executed I would have an IEnumerable<OperationStep> which I can write to a CSV file.
So the question is is there an easier way of achieving what I have done so far? The reporting is extremely tedious and time consuming to code, considering that the API library consists of hundreds of similar methods. Samples are described bellow:
OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);
Where the DomainContext is a singleton object whose functionality is to connect to the domain controller and create a user, group, and associate the user to a group.
Note that both the second and the third method call require the output of the first, and therefore warranting the need for having the public T Context within the OperationResult object as described bellow.
The OperationStep object consists of the following properties which are inherited by the IOperation interface with the exception of the public T Context.
public class OperationStep<T> : IOperation
{
/// <summary>
/// Denotes the Logical Name of the current operation
/// </summary>
public string Name { get; set; }
/// <summary>
/// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup
/// </summary>
public OperationStage Stage { get; set; }
/// <summary>
/// Denotes whether the test step completed properly or failed.
/// </summary>
public OperationResult Result { get; set; }
/// <summary>
/// Denotes the return type of the test method.
/// </summary>
public T Context { get; set; }
/// <summary>
/// Denotes any other relevant information about the test step
/// </summary>
public string Description { get; set; }
/// <summary>
/// If the test step result is failed, this should have the stack trace and the error message.
/// </summary>
public string Error { get; set; }
}
The method calls themselves are a bit bloated and tedious but here is a sample.
public class DomainContext
{
private static volatile DomainContext currentContext;
private static object synchronizationToken = new object();
/// <summary>
/// default ctor.
/// </summary>
private DomainContext() { }
/// <summary>
/// Retrieves the Current DomainContext instance.
/// </summary>
public static DomainContext Current
{
get
{
if (currentContext == null)
{
lock (synchronizationToken)
{
if (currentContext == null)
{
currentContext = new DomainContext();
}
}
}
return currentContext;
}
}
/// <summary>
/// Establishes a connection to the domain.
/// </summary>
/// <param name="domainInfo"></param>
/// <returns></returns>
public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
{
OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
result.Name = "Establish Connection to Active Directory";
result.Result = OperationResult.Success;
result.Stage = OperationStage.Setup;
result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);
try
{
ContextType contextType = this.GetContextType(domainInfo.DomainType);
PrincipalContext principalContext;
try
{
principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
}
catch
{
throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
}
if (principalContext != null)
{
bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);
if (!authenticationResult)
{
throw new Exception("Unable to authenticate domain admin user to Active Directory.");
}
result.Context = principalContext;
result.Result = OperationResult.Success;
}
}
catch(Exception ex)
{
result.Error = ex.Message;
result.Result = OperationResult.Failure;
}
return result;
}
}
When all method calls have executed theoreticaly I should have an IEnumerable<IOperation> which in the case of a win form I can write in a csv file (to be viewed in MS Excel) or in the case of a unit test I can simply omit the extra info and ignore (other than the method executed successively and the T Context property).
If I understood you correctly - all that OperationSteps are here only for logging. Then why not enable simple .NET logging? Log needed info where it is convenient for you. You can use TraceSource with DelimetedTraceListener to write to .csv file. More than that. You can move logging logic to Strategy class and override its logging methods in your unit test so that instead of logging you call Assert methods.

MVC Abstract Base Controller Override parameter type for modelbinding

For simplicity's sake, lets say I have the following Abstract Base Controller Class:
public abstract class RESTController : Controller
{
public abstract JsonResult List();
public abstract JsonResult Get(Guid id);
public abstract JsonResult Create(object obj);
public abstract JsonResult Update(object obj);
public abstract JsonResult Delete(Guid Id);
}
For the Create & Update methods, I not only want to override the Method, but also the type of the parameter.
Typically I would use generics like so:
public abstract JsonResult Create<T>(T obj);
However this is an MVC action, and there is no way to specify type parameters.
What are my options? If I leave it as (object obj) will the MVC model binder work correctly?
var model = obj as MyViewModel;
This isn't very clean in any case. Any help would be appreciated.
How about something among the lines:
public abstract class RESTController<T> : Controller
{
public abstract JsonResult List();
public abstract JsonResult Get(Guid id);
public abstract JsonResult Create(T obj);
public abstract JsonResult Update(T obj);
public abstract JsonResult Delete(Guid Id);
}
and when overriding:
public FooController: RESTController<Foo>
{
...
public override JsonResult Create(Foo obj)
{
throw new NotImplementedException();
}
...
}
If you want something a bit more fleshed out, you could try using something along the lines of the following. I'm using Onion Architecture and Repository Pattern, with IoC, and DI. IEntity simply provides access to the Id field of the entity (I'm assuming Entity Framework Code First here, with Entity.Id as the primary key for each entity, whereas EntityId would designate a foreign key on another table.).
The actions are virtual to allow derived classes to override them where necessary, and the repository is set to protected, so that the derived class can also pull from the repository for the entity. This works with a basic CRUD repository, but could be replaced with an aggregate to allow more functionality.
using System;
using System.Web.Mvc;
using MySolution.Core.Interfaces.EntityFramework;
using MySolution.Core.Interfaces.Repositories;
namespace MySolution.Ux.Web.Site.Primitives
{
/// <summary>
/// Provides mechanisms for performing CRUD operations on entities within a RESTful environment.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
public abstract class CrudController<TEntity> : Controller
where TEntity : class, IEntity, new()
{
/// <summary>
/// The repository to use for CRUD operations on the entity. Derived classes
/// also have access to this repository so that the virtual actions can be
/// overridden with custom implementations.
/// </summary>
protected readonly IRepository<TEntity> Repository;
/// <summary>
/// Initialises a new instance of the <see cref="CrudController{TEntity}"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
protected CrudController(IRepository<TEntity> repository)
{
// Instantiate the controller's repository.
Repository = repository;
}
/// <summary>
/// Lists this specified entities within the data store.
/// </summary>
/// <returns>A JSON formatted list of the entities retrieved.</returns>
[HttpGet]
public virtual JsonResult List()
{
try
{
return Json(Repository.GetAll(), JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(e.Message, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// Gets a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity retrieved.</returns>
[HttpGet]
public virtual JsonResult Get(Guid id)
{
try
{
return Json(Repository.Get(id), JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// Creates a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity created.</returns>
[HttpPost]
public virtual JsonResult Create(TEntity entity)
{
try
{
Repository.Add(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
/// <summary>
/// Updates a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity updated.</returns>
[HttpPut]
public virtual JsonResult Update(TEntity entity)
{
try
{
Repository.Update(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
/// <summary>
/// Deletes a specific entity from the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity deleted.</returns>
[HttpDelete]
public virtual JsonResult Delete(Guid id)
{
try
{
var entity = Repository.Get(id);
Repository.Remove(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
}
}

Categories

Resources