Named Constructor Dart, with no values - dart

I was going through some code when I found this snippet:
class DBHelper {
DBHelper._();
static final DBHelper db = DBHelper._();
static Database _database;
Future<Database> get database async {
if (_database == null) {
_database = await initDB();
}
return _database;
}
}
Can anyone simplify this definition of Named Constructor?
Also can there be any alternative way of achieving this functionality.

Related

ninject with datacontext and need for static implementation in MVC

I am using a .net standard class library to implement Entity Framework core on an existing ASP.NET MVC web application.
I am injecting the data context into the classes I am using, but I also need a static implementation for some specific method calls. The obvious issue here is that in the static context, I don't have an injected data context. so i did the following.
What is the correct way to do this?
I am using a Ninject Module in the library to map dependencies to the kernel in the web project.
namespace AppealTrack.Logic.Classes
{
using System;
using System.Collections.Generic;
using System.Linq;
using Common.Entities;
using Data;
using Interfaces;
using Microsoft.EntityFrameworkCore;
public class LookupLogic : ILookupLogic, IDisposable
{
private readonly AppealTrackDataContext _context;
public LookupLogic(AppealTrackDataContext context)
{
_context = context;
}
public List<County> GetCountries(string state)
{
var list = _context.Countries.Where(x => state == null || x.State == state).Distinct().AsNoTracking().ToList();
return list;
}
public void Dispose()
{
}
}
public static class LookupLogicStatic
{
public static List<County> GetCountries(string state)
{
// this is the part that I don't think is correct:
using (var logic = new LookupLogic(new AppealTrackDataContext()))
{
var list = logic.GetCountries(state);
return list;
}
}
}
}
If you require a static GetCountries method, then there is not much you can do... you would need to manage the scope of DbContext for that method as static constructor does not take any arguments. Your LookupLogic does not have to be Disposable though (it can be if you want).
If you require a static method, then you don't have to add a new static class, you can add the static method to LookupLogic:
public class LookupLogic : ILookupLogic
{
private readonly AppealTrackDataContext _context;
public LookupLogic(AppealTrackDataContext context)
{
_context = context;
}
public List<Country> GetCountries(string state)
{
return GetCountries(_context, state);
}
public static List<Country> GetCountriesStatic(string state)
{
using (var dbContext = new AppealTrackDataContext())
{
return GetCountries(dbContext, state);
}
}
private static List<Country> GetCountries(AppealTrackDataContext dbContext, string state)
{
return dbContext.Countries.Where(x => state == null || x.State == state).Distinct().AsNoTracking().ToList();
}
}

Implement dependency injection in background services in Xamarin Forms using Prism

I am making use of Prism in my xamarin forms project.I was able to use dependency injection(constructor injection) in my View Model without any problems.I am also making use of background services to push long running tasks in the background.How do I inject dependency in my Background services?When I try to pass the interface object as a paramater to the constructor(SyncingBackgroundingCode) ,the object(SqliteService) is null.I have registered and resolved the objects in the dependency injection container.
How to handle this case?Can anybody provide an example or link to implement this scenario?
This is the piece of code where im trying to implement dependency injection.
This is in Droid :-
public class AndroidSyncBackgroundService : Service
{
CancellationTokenSource _cts;
public override IBinder OnBind (Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
{
_cts = new CancellationTokenSource ();
Task.Run (() => {
try {
//INVOKE THE SHARED CODE
var oBackground = new SyncingBackgroundingCode();
oBackground.RunBackgroundingCode(_cts.Token).Wait();
}
catch (OperationCanceledException)
{
}
finally {
if (_cts.IsCancellationRequested)
{
var message = new CancelledTask();
Device.BeginInvokeOnMainThread (
() => MessagingCenter.Send(message, "CancelledTask")
);
}
}
}, _cts.Token);
return StartCommandResult.Sticky;
}
public override void OnDestroy ()
{
if (_cts != null) {
_cts.Token.ThrowIfCancellationRequested ();
_cts.Cancel ();
}
base.OnDestroy ();
}
}
This is in PCL:-
public class SyncingBackgroundingCode
{
public SQLiteConnection _sqlconnection;
SqliteCalls oSQLite = new SqliteCalls();
ISqliteService _SqliteService;
public SyncingBackgroundingCode(ISqliteService SqliteService)
{
//object is null
}
public async Task RunBackgroundingCode(CancellationToken token)
{
DependencyService.Get<ISQLite>().GetConnection();
await Task.Run (async () => {
token.ThrowIfCancellationRequested();
if (App.oSqliteCallsMainLH != null)
{
App.bRunningBackgroundTask = true;
oSQLite = App.oSqliteCallsMainLH;
await Task.Run(async () =>
{
await Task.Delay(1);
oSQLite.ftnSaveOnlineModeXMLFormat("Offline", 0);
oSQLite.SyncEmployeeTableData();
oSQLite.SaveOfflineAppCommentData();
oSQLite.SaveOfflineAdditionToFlowData();
await Task.Delay(500);
var msgStopSyncBackgroundingTask = new StopSyncBackgroundingTask();
MessagingCenter.Send(msgStopSyncBackgroundingTask, "StopSyncBackgroundingTask");
});
}
}, token);
}
}
Unfortunately Xamarin and Xamarin Forms don't give frameworks like Prism anywhere to tie into to handle IoC scenarios. There are a couple of ways you can handle this though.
First the Container is a public property on the PrismApplication in your background service you could do something like:
public class FooBackgroundService
{
private App _app => (App)Xamarin.Forms.Application.Current;
private void DoFoo()
{
var sqlite = _app.Container.Resolve<ISQLite>();
}
}
Another slightly more involved way would be to use the ServiceLocator pattern. You might have something like the following:
public static class Locator
{
private static Func<Type, object> _resolver;
public static T ResolveService<T>() =>
(T)_resolver?.Invoke(typeof(T));
public static void SetResolver(Func<Type, object> resolver) =>
_resolver = resolver;
}
In your app you would then simply set the resolver. Prism actually does something similar to this with the ViewModel locator, which then allows it to inject the correct instance of the NavigationService.
public class App : PrismApplication
{
protected override void OnInitialized()
{
SetServiceLocator();
NavigationService.NavigateAsync("MainPage");
}
protected override void RegisterTypes()
{
// RegisterTypes
}
private void SetServiceLocator()
{
Locator.SetResolver(type => Container.Resolve(type, true));
}
}
Finally your service would simply reference the Service Locator like:
public class BarBackgroundService
{
public void DoBar()
{
var sqlite = Locator.ResolveService<ISQLite>();
// do foo
}
}

What would cause NHibernate's Save method to fail silently?

I've been tasked with taking over an existing ASP.NET MVC 2.0 web application that was developed by a third party developer who is no longer around to provide any assistance. There has been a requirement to add some functionality to the project, which required a project upgrade to .NET 4.5, which has been performed.
The sites underlying MSSQL 2008 R2 database access has been implemented using NHibernate version 2.0.1.4000, along with Castle and FluentNHibernate.
This is the first project I've been involved in that has used NHibernate, and I've hit a problem that has me stumped. The problem did not exist until the upgrade to .NET 4.5.
All database operations are working normally, except for one. Saving a particular object (
Opportunity type) to the database (this object directly maps to an Opportunity database table) fails. Prior to saving (in this case a SQL UPDATE statement), the object has new values set. But the record in the database always has the old values after saving.
Hooking up log4net to view the debug code, shows that the record is indeed updated, but using the old values in the UPDATE statement.
Surprisingly, the Opportunity object is intially saved using the same Save method (albeit via a different action method), and that is saving to the database just fine.
So my question is, what would cause this to happen? Being that I'm not an NHibernate expert, is it the case that the NHibernate version is simply incompatible with .NET 4.5? Or can anyone provide a pointer as to what the problem might be? I'm happy to show any code, but as there is so much I would need to know what. Below is a starter:
The Global.asax has the following references to NHibernate:
private static void MvcApplication_BeginRequest(object sender, System.EventArgs e)
{
NHibernateSessionManager.Instance.BeginTransaction();
}
private static void MvcApplication_EndRequest(object sender, System.EventArgs e)
{
NHibernateSessionManager.Instance.CommitTransaction();
}
The NHibernateSessionManager class is defined as (Opportunity derives from DomainBase):
public sealed class NHibernateSessionManager
{
private ISessionFactory sessionFactory;
private Configuration config;
#region Thread-safe, lazy Singleton
public static NHibernateSessionManager Instance
{
get
{
return Nested.nHibernateSessionManager;
}
}
private NHibernateSessionManager()
{
InitSessionFactory();
}
private class Nested
{
internal static readonly NHibernateSessionManager nHibernateSessionManager = new NHibernateSessionManager();
}
#endregion
private void InitSessionFactory()
{
var autoMappings = AutoPersistenceModel.MapEntitiesFromAssemblyOf<DomainBase>()
.Where(type =>
typeof(DomainBase).IsAssignableFrom(type) &&
type.IsClass &&
!type.IsAbstract)
.WithSetup(s =>
{
s.IsBaseType = type =>
type == typeof (DomainBase);
})
.UseOverridesFromAssemblyOf<OpportunityMappingOverride>()
.ConventionDiscovery.Add(DefaultLazy.AlwaysTrue())
.ConventionDiscovery.Add<CascadeAllHasOneConvention>()
.ConventionDiscovery.Add<CascadeAllHasManyConvention>()
.ConventionDiscovery.Add<CascadeAllReferenceConvention>();
sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(c => c.FromConnectionStringWithKey("Default"))
.UseReflectionOptimizer()
.Cache(c => c.UseQueryCache().UseMininmalPuts().ProviderClass<SysCacheProvider>())
.ShowSql())
.Mappings(m => m.AutoMappings.Add(autoMappings))
.ExposeConfiguration(SetConfiguration)
.BuildSessionFactory();
}
private void SetConfiguration(Configuration cfg)
{
config = cfg;
}
public void RegisterInterceptor(IInterceptor interceptor)
{
ISession session = threadSession;
if (session != null && session.IsOpen)
{
throw new CacheException("You cannot register an interceptor once a Session has already been opened");
}
GetSession(interceptor);
}
public void GenerateSchema()
{
new SchemaExport(config).Execute(false, true, false, false);
}
public ISession GetSession()
{
return GetSession(null);
}
private ISession GetSession(IInterceptor interceptor)
{
ISession session = threadSession;
if (session == null)
{
if (interceptor != null)
{
session = sessionFactory.OpenSession(interceptor);
}
else
{
session = sessionFactory.OpenSession();
}
threadSession = session;
}
return session;
}
public void CloseSession()
{
ISession session = threadSession;
threadSession = null;
if (session != null && session.IsOpen)
{
session.Close();
}
}
public void BeginTransaction()
{
ITransaction transaction = threadTransaction;
if (transaction == null)
{
transaction = GetSession().BeginTransaction();
threadTransaction = transaction;
}
}
public void CommitTransaction()
{
ITransaction transaction = threadTransaction;
try
{
if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
{
transaction.Commit();
threadTransaction = null;
}
}
catch (HibernateException)
{
RollbackTransaction();
throw;
}
}
public void RollbackTransaction()
{
ITransaction transaction = threadTransaction;
try
{
threadTransaction = null;
if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
{
transaction.Rollback();
}
}
finally
{
CloseSession();
}
}
private static ITransaction threadTransaction
{
get
{
return (ITransaction)CallContext.GetData("THREAD_TRANSACTION");
}
set
{
CallContext.SetData("THREAD_TRANSACTION", value);
}
}
private static ISession threadSession
{
get
{
return (ISession)CallContext.GetData("THREAD_SESSION");
}
set
{
CallContext.SetData("THREAD_SESSION", value);
}
}
}
I'm hoping I won't get shot down for this question being too general. I've spent a day trying to work out what is happening, including extensive searches online.
It turned out the problem was that the NHibernateSessionManager class was storing its ITransaction and ISession objects in System.Runtime.Remoting.Messaging.CallContext.
Swapping it out to store the objects in the HttpContext.Current.Items collection resolved the issue.
I found this post which implies .NET 4.5 handles CallContext slightly differently compared with previous versions, which obviously caused my issue.
Because the NHibernateSessionManager class was in a class library that was also used by a couple of rarely used console applications, I left a fallback to the CallContext object as per below (not pretty, and there might have been an better alternative, but worked for me [subject to testing], as I've spent far to long figuring this one out using remote debugging):
private static ITransaction threadTransaction
{
get
{
try
{
return (ITransaction)System.Web.HttpContext.Current.Items["THREAD_TRANSACTION"];
}
catch
{
return (ITransaction)CallContext.GetData("THREAD_TRANSACTION");
}
}
set
{
try
{
System.Web.HttpContext.Current.Items["THREAD_TRANSACTION"] = value;
}
catch
{
CallContext.SetData("THREAD_TRANSACTION", value);
}
}
}
private static ISession threadSession
{
get
{
try
{
return (ISession)System.Web.HttpContext.Current.Items["THREAD_SESSION"];
}
catch
{
return (ISession)CallContext.GetData("THREAD_SESSION");
}
}
set
{
try
{
System.Web.HttpContext.Current.Items["THREAD_SESSION"] = value;
}
catch
{
CallContext.SetData("THREAD_SESSION", value);
}
}
}

Join Multiple Transactions Across Instances of EF Connections

I have the following setup in my Data Layer
namespace DAL
{
public abstract class BaseDalObj:IDisposable
{
protected Auto.Entities entities;
public BaseDalObj()
{
entities= new Auto.Entities();
}
public void Dispose()
{
}
}
public class Class1: BaseDalObj
{
public void Save(object a)
{
entities.SaveItem(a);
}
}
public class Class2: BaseDalObj
{
public void Save(object b)
{
entities.SaveItem(b);
}
}
}
namespace Business
{
public class BusinessLL
{
public Object a,b;
public BusinessDAL()
{
a = new Object();
b = new Object();
}
public void Save()
{
using(var dbObj1 = new DAL.Class1())
{
dbObj1.Save(a);
using(var dbObj2 = new DAL.Class2())
{
dbObj2.Save(b);
}
}
}
}
}
what I would like is some way to call both Save functions but within the same TransactionScope.
I have no idea how i can do this using EF. I have looked into using the TransactionScope Class but I cannot get to grips with how it works.
I have been looking at using the entities.Connection.BeginTransaction() but that returns a DbTransaction and TransactionScope only accepts a type Transaction Class
Any help or pointers that can point me in the right way would really help.
If there is an ambient transaction present when opening a connection the connection will automatically enlist into this transaction. This applies to the ObjectContext too - when you call ObjectContext.SaveChanges it will automatically enlist the connection into the ambient transaction.
Therefore, I think this should work:
using(var transaction = new TransactionScope)
{
using(var class1 = new Class1())
{
class1.Save(x);
}
using(var class2 = new Class2())
{
class2.Save(y);
}
transaction.Complete();
}

ASP.NET MVC - How to access Session data in places other than Controller and Views

We can access session data in controllers and views like this:
Session["SessionKey1"]
How do you access Session values from a class other than a controller or view?
I'd use dependency injection and pass the instance of the HttpContext (or just the session) to the class that needs access to the Session. The other alternative is to reference HttpContext.Current, but that will make it harder to test since it's a static object.
public ActionResult MyAction()
{
var foo = new Foo( this.HttpContext );
...
}
public class Foo
{
private HttpContextBase Context { get; set; }
public Foo( HttpContextBase context )
{
this.Context = context;
}
public void Bar()
{
var value = this.Context.Session["barKey"];
...
}
}
You just need to call it through the HttpContext like so:
HttpContext.Current.Session["MyValue"] = "Something";
Here is my version of a solution for this problem. Notice that I also use a dependency injection as well, the only major difference is that the "session" object is accessed through a Singleton
private iSession _Session;
private iSession InternalSession
{
get
{
if (_Session == null)
{
_Session = new SessionDecorator(this.Session);
}
return _Session;
}
}
Here is the SessionDecorator class, which uses a Decorator pattern to wrap the session around an interface :
public class SessionDecorator : iSession
{
private HttpSessionStateBase _Session;
private const string SESSIONKEY1= "SESSIONKEY1";
private const string SESSIONKEY2= "SESSIONKEY2";
public SessionDecorator(HttpSessionStateBase session)
{
_Session = session;
}
int iSession.AValue
{
get
{
return _Session[SESSIONKEY1] == null ? 1 : Convert.ToInt32(_Session[SESSIONKEY1]);
}
set
{
_Session[SESSIONKEY1] = value;
}
}
int iSession.AnotherValue
{
get
{
return _Session[SESSIONKEY2] == null ? 0 : Convert.ToInt32(_Session[SESSIONKEY2]);
}
set
{
_Session[SESSIONKEY2] = value;
}
}
}`
Hope this helps :)
Haven't done it myself, but this sample from Chad Meyer's blog might help (from this post: http://www.chadmyers.com/Blog/archive/2007/11/30/asp.net-webforms-and-mvc-in-the-same-project.aspx)
[ControllerAction]
public void Edit(int id)
{
IHttpSessionState session = HttpContext.Session;
if (session["LoggedIn"] == null || ((bool)session["LoggedIn"] != true))
RenderView("NotLoggedIn");
Product p = SomeFancyDataAccess.GetProductByID(id);
RenderView("Edit", p);
}
I would also wrap all session variables into a single class file. That way you can use intelliSense to select them. This cuts down on the number of paces in code where you need to specify the "strings" for the session.

Resources