Setting the DataContext on an Entity instance after it's retrieved - vb.net

I'm trying to find a way to have the DataContext available from within Entities.
I want to do something like this:
partial public class MyEntity
public DataContext as MyDataContext
private sub OnLoaded()
Me.DataContext = <the context that retrieved this instance>
end sub
end class
First, can something like this be done?
Second, assuming that I'm not going to use this entity with any other DataContext, is there any dangers or gotchas in doing such a thing?
This is the way I do it currently:
partial public class MyDataContext
public function GetMyEntity(byval id as integer) as MyEntity
dim o = MyEntities.SingleOrDefault(function(e) e.id = id)
if o isnot nothing then o.DataContext = Me
return o
end function
end class

Although you didn't specify a real reason for it, just a sidenote from MSDN:
In general, a DataContext instance is
designed to last for one "unit of
work" however your application defines
that term. A DataContext is
lightweight and is not expensive to
create. A typical LINQ to SQL
application creates DataContext
instances at method scope or as a
member of short-lived classes that
represent a logical set of related
database operations.
and one more:
Do not try to reuse instances of
DataContext. Each DataContext
maintains state (including an identity
cache) for one particular edit/query
session. To obtain new instances based
on the current state of the database,
use a new DataContext.
and finally,
... Any instance members are not
guaranteed to be thread safe.
But still in some cases semi-persistent solutions could be very helpful. Take a look onto Rick Strachl's article: Linq to SQL DataContext Lifetime Management. There are different approaches of DataContext management is reviewed in it. On of them - Create a per business object DataContext is exactly what you need.

You could use a singleton pattern on the DataContext, but you will need some kind of lifetime management on it, as it is not good to keep it around to long. (request ends dispose it maybe)
Example in C#, but I hope you can understand it.
public class MyDataContext
{
public static MyDataContext Current
{
get
{
MyDataContext context = (MyDataContext)HttpContext.Current.Items["Context"];
if(context == null)
{
context = new MyDataContext();
HttpContext.Current.Items["Context"] = context;
}
return context;
}
}
}
public class MyEntity
{
public MyDataContext DataContext
{
get{ return MyDataContext.Current;}
}
}
In Global.asax you can hook up the event Application_EndRequest and call MyDataContext.Current.Dispose(); to dispose of the context manually instead of waiting for the GC to do it.

Related

confusion over using transient or scoped or singleton in .NetCore

Hey Guys i'm very new in software development,I still no idea when to use which,whats the meaning of service lifetime!it may seem stupid but please help me,i have an interface :
public interface IAccessInfo
{
public IEnumerable<AccessInfo> getResult();
}
what it supposed to do is to returns me the information about my Turbines;here is the implementation of it :
public class AcessInfoData:IAccessInfo
{
private DbContextClass db;
public AcessInfoData(DbContextClass context)
{
db = context;
}
public IEnumerable<AccessInfo> getResult()
{
var turbines = (from c in db.accessinf
where s.user_id == "i0004912"
select new AccessInfo
{
InfoType = c.type,
TurbineId = c.m_plc_id.ToString(),
TurbineIP = c.turbine_ip.ToString(),
TurbineIdSorting = c.turbine_id,
Blade = c.blade,
Certification = c.certification,
}).Distinct();
return turbines;
}
}
it gets an instance of my DB and gets the data;and in my controller i use it like this:
public class AcessInfoController : ControllerBase
{
private IAccessInfo _acess;
public AcessInfoController(IAccessInfo access)
{
_acess = access;
}
[HttpGet]
public IActionResult Index()
{
var rsult = _acess.getResult();
return Ok( rsult);
}
}
now in the Startup i registered it :
services.AddScoped<IAccessInfo, AcessInfoData>();
it works,but if you sk me why i user Scoped and not Singleton or transient i have no idea why,really,any one can make it clear for me?
I will try to explain a little about the mentioned cases:
scoped : For all needs of an object during the life of an operation (such as a request from the client) a single instance of the object is created. (It means that only one instance of the object is sent for all requirements during life time of a request)
Singleton: Creates only one instance of object and sends it for all requirements in the application scope.(For all needs everywhere in the program, only one instance of the object is sent, a bit like static objects).
Transient: Ioc container, makes an instance of object whenever code needs it, that is, it makes an instance for each requirement anywhere in the program and at any time, which means that if the program needs an object 3 times, it makes an independent instance for each.
Instance: In this case, each time an object is needed, only one instance of it is provided to the program, which you defined it in the startup section. (when defining it in the startup section, you specify how to create an instance).
I hope to reduce some of the ambiguities.

Tuning Entity Framework - dbContext?

I have some model class:
Public Class MyViewModel
Public Property MyID() As Integer
Public ReadOnly Property FirstList As IEnumerable(Of SelectListItem)
Get
Using dbContext As New MyContext
Dim itemQuery = (From t In dbContext.ItemSet Select t)
Dim item As IEnumerable(Of Item) = itemQuery.ToList()
Return item.Select(Function(o) New SelectListItem() With {.Text = o.ItemDesc, .Value = o.ID})
End Using
End Get
End Property
Public ReadOnly Property SecondList As IEnumerable(Of SelectListItem)
Get
Using dbContext As New MyContext
Dim _Query = (From t In dbContext.FrameworkSet Select t)
Dim _list As IEnumerable(Of Item2) = _Query.ToList()
Return _list.Select(Function(o) New SelectListItem() With {.Text = o.Item2Desc, .Value = o.ID})
End Using
End Get
End Property
End Class
Basically, I'm calling MyContext twice. This instantiates EF repeatedly, correct? So my thought is just have a class global
Dim dbContext as New MyContext
Aside from Code Analysis telling me I need to implement IDisposable (which according to this: http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html#.U6WdzrGEeTw I needn't worry about?)
I'm confused - what's the accepted best practice?
In addition to Phil Soady's comments (which, briefly, are not to store the context in a global variable and instead prefer short lived disposed contexts) I'd like to point out that much of the context initialization is not done per construction of the object but rather once for the lifetime of the application. This is mainly the process of building its internal model, which it does and then caches.
Check out more detail here: http://blog.oneunicorn.com/2011/04/15/code-first-inside-dbcontext-initialization/
Using block is ideal for EF.
Global variable for context is a recipe for nightmares. The Context is not threadsafe and is intended for short use.
Keeping the context for several operations in a logical flow is common.
Since the context content can be reused. Change detection , unit of work commit control are all part of EF. But dont try a keep the context for an extended period. You may have more performance problems with the context that way as the context may grow. You also have the multi user and concurrency issues to consider. Even a simple standalone APP on PC i would Create and dispose (using) the content on each "button" click in an app.

Linq to SQL - Attribute based mapping - cannot instantiate new object with no arguments

I want to extend Linq's DataContext class to implement the ORM. Currently my model looks like this:
public class Trial : DataContext
{
public Trial(string connectionString) : base(connectionString) { }
[Column(DbType = "System.Guid", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public Guid TrialID { get; set; }
//...
}
However when I try to instantiate a new Trial object to insert it into the database I get an error complaining that Trial does not have a constructor that takes 0 arguments. When I try to create such a constructor, VS complains that DataContext does not have a constructor that takes 0 arguments.
Am I missing something here? How do I seperate the data context from the model definition?
(First time using Linq!)
Thanks in advance,
Max.
Your data context that represents the database view should inherit from DataContext. It should expose Tables where T is the entities (rows) that you want to add. Try generating a model from the database using the designer or SQLMetal and take a closer look at the generated code to see what's going on.

Optimum Way To Restore Domain Object

This is such a simple and common scenario I wonder how did I managed until now and why I have problems now.
I have this object (part of the Infrastructure assembly)
public class Queue {}
public class QueueItem
{
public QueueItem(int blogId,string name,Type command,object data)
{
if (name == null) throw new ArgumentNullException("name");
if (command == null) throw new ArgumentNullException("command");
BlogId = blogId;
CommandType = command;
ParamValue = data;
CommandName = name;
AddedOn = DateTime.UtcNow;
}
public Guid Id { get; internal set; }
public int BlogId { get; private set; }
public string CommandName { get; set; }
public Type CommandType { get; private set; }
public object ParamValue { get; private set; }
public DateTime AddedOn { get; private set; }
public DateTime? ExecutedOn { get; private set; }
public void ExecuteIn(ILifetimeScope ioc)
{
throw new NotImplementedException();
}
}
This will be created in another assembly like this
var qi = new QueueItem(1,"myname",typeof(MyCommand),null);
Nothing unusal here. However, this object will be sent t oa repository where it will be persisted.The Queue object will ask the repository for items. The repository should re-create QueueItem objects.
However, as you see, the QueueItem properties are invariable, the AddedOn property should be set only once when the item is created. The Id property will be set by the Queue object (this is not important).
The question is how should I recreate the QueueItem in the repository? I can have another constructor which will require every value for ALL the properties, but I don't want that constructor available for the assembly that will create the queue item initially. The repository is part of a different assembly so internal won't work.
I thought about providing a factory method
class QueueItem
{
/* ..rest of definitions.. */
public static QueueItem Restore(/* list of params*/){}
}
which at least clears the intent, but I don't know why I don't like this approach. I could also enforce the item creation only by the Queue , but that means to pass the Queue as a dependency to the repo which again isn't something I'd like. To have a specific factory object for this, also seems way overkill.
Basically my question is: what is the optimum way to recreate an object in the repository, without exposing that specific creational functionality to another consumer object.
Update
It's important to note that by repository I mean the pattern itself as an abstraction, not a wrapper over an ORM. It doesn't matter how or where the domain objects are persisted. It matters how can be re-created by the repository. Another important thing is that my domain model is different from the persistence model. I do use a RDBMS but I think this is just an implementation detail which should not bear any importance, since I'm looking for way that doesn't depend on a specific storage access.
While this is a specific scenario, it can applied to basically every object that will be restored by the repo.
Update2
Ok I don't know how I could forget about AutoMapper. I was under the wrong impression it can't map private fields/setter but it can, and I think this is the best solution.
In fact I can say the optimum solutions (IMO) are in order:
Directly deserializing, if available.
Automap.
Factory method on the domain object itself.
The first two don't require the object to do anyting in particular, while the third requires the object to provide functionality for that case (a way to enter valid state data). It has clear intent but it pretty much does a mapper job.
Answer Updated
To answer myself, in this case the optimum way is to use a factory method. Initially I opted for the Automapper but I found myself using the factory method more often. Automapper can be useful sometimes but in quite a lot of cases it's not enough.
An ORM framework would take care of that for you. You just have to tell it to rehydrate an object and a regular instance of the domain class will be served to you (sometimes you only have to declare properties as virtual or protected, in NHibernate for instance). The reason is because under the hood, they usually operate on proxy objects derived from your base classes, allowing you to keep these base classes intact.
If you want to implement your own persistence layer though, it's a whole nother story. Rehydrating an object from the database without breaking the scope constraints originally defined in the object is likely to involve reflection. You also have to think about a lot of side concerns : if your object has a reference to another object, you must rehydrate that one before, etc.
You can have a look at that tutorial : Build Your Own dataAccess Layer although I wouldn't recommend reinventing the wheel in most cases.
You talked about a factory method on the object itself. But DDD states that entities should be created by a factory. So you should have a QueueItemFactory that can create new QueueItems and restore existing QueueItems.
Ok I don't know how I could forget about AutoMapper.
I wish I could forget about AutoMapper. Just looking at the hideous API gives me shivers down my spine.

What is the correct way to use Unit of Work/Repositories within the business layer?

Having built a small application using the Unit of Work/Repository pattern, I am struggling to understand how to use this properly within my business layer. My application has a a data access layer which can be either NHibernate or the Entity Framework. I can switch between these easily.
I have a number of repositories, for example, Customer, Order etc. My unit of work will be either an ISession or an Object Context depending on which DAL I want to test with.
My business layer contains a single business method - CreateOrder(). What I am struggling to understand is where in the business layer I should be initialising my unit of work and my repositories.
Focusing on Nhibernate, my DAL looks like:
public class NHibernateDAL : IUnitOfWork
{
log4net.ILog log = log4net.LogManager.GetLogger(typeof(NHibernateDAL));
ISession context;
public NHibernateDAL()
{
context = SessionProvider.OpenSession();
this.Context.BeginTransaction();
CurrentSessionContext.Bind(context);
}
public ISession Context
{
get { return context; }
}
public void Commit()
{
this.Context.Transaction.Commit();
context.Close();
}
public void Dispose()
{
ISession session = CurrentSessionContext.Unbind(SessionProvider.SessionFactory);
session.Close();
}
}
Within my business layer, I want to know where I should be declaring my Unit of Work and repositories. Are they declared at class level or within the CreateOrder method?
For example:
public class BusinessLogic
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
NhRepository<Order> _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = new NhRepository<Customer>(_unitOfWork);
....
public void CreateOrder(.....)
{
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
The above code works only for the first time the CreateOrder() method is called, but not for subsequent calls because the session is closed. I have tried removing the 'context.Close()' call after committing the transaction but this also fails. Although the above approach doesn't work, it seems more correct to me to declare my repositories and unit of work with this scope.
However, if I implement it as below instead it works fine, but it seems unnatural to declare the repositories and unit of work within the scope of the method itself. If I had a tonne of business methods then I would be declaring repositories and Units of Work all over the place:
public class BusinessLogic
{
public void CreateOrder(.....)
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
var _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = null;
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
If I were to implement this with class level declaration then I think I would need some means of re-opening the same unit of work at the start of the CreateOrder method.
What is the correct way to use the unit of work and repositories within the business layer?
Looks to me like you've almost got it. In our new server stack I have this setup:
WCF Service Layer --> just returns results from my Business Layer
My business layer is called, creates a unitofwork, creates the respository
Calls the respository function
Uses AutoMapper to move returned results into a DTO
My repository gets the query results and populates a composite object.
Looks almost like what you've got there. Though we use Unity to locate what you call the business layer. (we just call it our function processor)
What I would highly suggest, though, is that you do NOT keep the UnitOfWork at the class level. After all each descreet function is a unit of work. So mine is like this (the names have been changed to protect the innocent):
using ( UnitOfWorkScope scope = new UnitOfWorkScope( TransactionMode.Default ) )
{
ProcessRepository repository = new ProcessRepository( );
CompositionResultSet result = repository.Get( key );
scope.Commit( );
MapData( );
return AutoMapper.Mapper.Map<ProcessSetDTO>( result );
}
We also had a long discussion on when to do a scope.Commit and while it isn't needed for queries, it establishes a consistent pattern for every function in the application layer. BTW we are using NCommon for our repository/unitofwork patterns and do not have to pass the UoW to the repository.
Your IUnitOfWork implementation contains all repositories.
Your IUnitOfWork is injected into your presentation layer like mvc controller.
Your IUnitOfWork is injected into mvc controller.
Your IRepository is injected into your UnitOfWork implementation.