Altering multiple databases with NHibernate - c#

I'm having trouble with the copying entities between multiple databases. I can't seem to get my head around this issue and really need some help with the implementation.
My current implementation is described here:
Http module
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using ISMSControl.Infrastructure.Sessions;
using NHibernate;
using NHibernate.Context;
namespace ISMSControl.Infrastructure.Modules
{
public class SessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OpenSession;
context.EndRequest += CloseSession;
}
private void CloseSession(object sender, EventArgs e)
{
ISession session = ManagedWebSessionContext.Unbind(HttpContext.Current, SessionManager.GetCurrentSession().SessionFactory);
if (session != null)
{
if (session.Transaction != null && session.Transaction.IsActive)
session.Transaction.Rollback();
else
session.Flush();
session.Close();
}
}
private void OpenSession(object sender, EventArgs e)
{
ManagedWebSessionContext.Bind(HttpContext.Current,
SessionManager.GetCurrentSession());
}
public void Dispose()
{
}
}
}
SessionManager implemenation
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using ISMSControl.Infrastructure.Mappings;
using NHibernate;
using NHibernate.Cache;
namespace ISMSControl.Infrastructure.Sessions
{
public sealed class SessionManager
{
private const string CurrentSessionKey = "nhibernate.current_session";
private static readonly ISessionFactory sessionFactory;
static SessionManager()
{
sessionFactory = CreateSessionFactory("source");
}
private static ISessionFactory CreateSessionFactory(string connectionStringName)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString(c => c.FromConnectionStringWithKey(connectionStringName)))
.CurrentSessionContext("managed_web")
.Cache(c =>
{
c.UseQueryCache();
c.ProviderClass<HashtableCacheProvider>();
})
.Diagnostics(d =>
{
d.Enable();
d.OutputToConsole();
})
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<StandardMapping>())
.BuildSessionFactory();
}
public static ISession GetCurrentSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if (currentSession == null)
{
currentSession = sessionFactory.OpenSession();
context.Items[CurrentSessionKey] = currentSession;
}
return currentSession;
}
public static void CloseSession()
{
HttpContext context = HttpContext.Current;
ISession currentSession = context.Items[CurrentSessionKey] as ISession;
if (currentSession == null)
{
// No current session
return;
}
currentSession.Close();
context.Items.Remove(CurrentSessionKey);
}
public static void CloseSessionFactory(string sessionFactoryName = null)
{
if (sessionFactory != null)
{
sessionFactory.Close();
}
}
}
}
Repository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Web;
using ISMSControl.Domain;
using ISMSControl.Domain.Contracts;
using ISMSControl.Infrastructure.Sessions;
using NHibernate;
using NHibernate.Context;
namespace ISMSControl.Infrastructure.Repositories
{
public class StandardRepository : IStandardRepository
{
public void SaveOrUpdate(Standard standard)
{
var session = SessionManager.GetCurrentSession();
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(standard);
transaction.Commit();
}
}
public IEnumerable<Standard> RetrieveList()
{
return SessionManager.GetCurrentSession().CreateCriteria<Standard>().List<Standard>();
}
public void CopyTo(string database, Standard standard)
{
//how do i implement this method, so it will copy the standard entity to the other database?
}
}
}
The problem is that i'm getting all these different kind of errors like, "The session is closed.", "The entity belows to another transaction or something". "Illegal attempt to associate a collection with two open sessions".
I really hope that someone can help me out our point me in the right direction by sharing a
Tutorial
Example
etc.
CopyTo implemenation
public void CopyTo(string sessionFactoryName, Standard standard)
{
//gets a new session for the destination database from the destination sessionfactory.
using (var destinationSession = SessionFactoryContainer.Current.Get(sessionFactoryName).OpenSession())
{
//error: no persister for...
var newStandard = new Standard();
newStandard.Code = standard.Code;
newStandard.Description = standard.Description;
newStandard.Explanation = standard.Explanation;
destinationSession.Save(newStandard);
}
}

In your "CopyTo" method, you have to create a session on the second database, deep clone the second parameter of your method and then attach the cloned object to the session you opened.

Related

Xamarin SQLite Database Check

I am new to Xamarin. I want to confirm if the database is created and if the data is being inserted to the SQLite database. Thank you for the help
Questions:
1. How to check if database exist/created or not?
2. How to check if the user are inserted successfully or it failed?
3. Where do these file go in my phone?
Below is my code:
App.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using TBSMobileApplication.Views;
using TBSMobileApplication.Data;
[assembly: XamlCompilation (XamlCompilationOptions.Compile)]
namespace TBSMobileApplication
{
public partial class App : Application
{
static TokenDatabaseController tokenDatabase;
static UserDatabaseController userDatabase;
public App ()
{
InitializeComponent();
MainPage = new LoginPage();
}
protected override void OnStart ()
{
// Handle when your app starts
}
protected override void OnSleep ()
{
// Handle when your app sleeps
}
protected override void OnResume ()
{
// Handle when your app resumes
}
public static UserDatabaseController UserDatabase
{
get
{
if(userDatabase == null)
{
userDatabase = new UserDatabaseController();
}
return userDatabase;
}
}
public static TokenDatabaseController TokenDatabase
{
get
{
if (tokenDatabase == null)
{
tokenDatabase = new TokenDatabaseController();
}
return tokenDatabase;
}
}
}
}
LoginPage.xaml.cs (Basically this is my Code behind in my login page)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TBSMobileApplication.Models;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TBSMobileApplication.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoginPage : ContentPage
{
public LoginPage ()
{
InitializeComponent ();
}
void LoginProcedure(object sender, EventArgs e)
{
User user = new User(entUser.Text, entPassword.Text);
if (user.CheckInformation())
{
//DisplayAlert("Login Message", "Login Success", "Ok");
try
{
App.UserDatabase.SaveUser(user);
DisplayAlert("Database Message", "User Saved", "Ok");
}
catch(Exception ex)
{
DisplayAlert("Message", ex.Message, "Ok");
}
}
else
{
DisplayAlert("Login Message", "Login Failed", "Ok");
}
}
}
}
ISQLite.cs (This is where you get the connection to the database)
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;
namespace TBSMobileApplication.Data
{
public interface ISQLite
{
SQLiteConnection GetConnection();
}
}
User.cs (This is where the parameters of the User table)
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;
namespace TBSMobileApplication.Models
{
public class User
{
[PrimaryKey, AutoIncrement]
public int ContactID { get; set; }
[Unique]
public string UserID { get; set; }
public string UserPassword { get; set; }
public User() { }
public User(string Username, string Password)
{
this.UserID = Username;
this.UserPassword = Password;
}
public bool CheckInformation()
{
if(!this.UserID.Equals("") || !this.UserPassword.Equals(""))
{
return true;
}
else
{
return false;
}
}
}
}
SQLite_Android.cs (This is where I created the database)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using TBSMobileApplication.Data;
using TBSMobileApplication.Droid.Data;
using Xamarin.Forms;
[assembly: Dependency(typeof(SQLite_Android))]
namespace TBSMobileApplication.Droid.Data
{
public class SQLite_Android : ISQLite
{
public SQLite_Android() { }
public SQLite.SQLiteConnection GetConnection()
{
var DBFileName = "backend.db3";
string DocumentPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var path = Path.Combine(DocumentPath, DBFileName);
var conn = new SQLite.SQLiteConnection(path);
return conn;
}
}
}
UserDatabaseController.cs (This is where I control User table like adding, deleting or getting data from User table)
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;
using TBSMobileApplication.Models;
using Xamarin.Forms;
namespace TBSMobileApplication.Data
{
public class UserDatabaseController
{
static object locker = new object();
SQLiteConnection database;
public UserDatabaseController()
{
database = DependencyService.Get<ISQLite>().GetConnection();
database.CreateTable<User>();
}
public User GetUser()
{
lock (locker)
{
if(database.Table<User>().Count() == 0)
{
return null;
}
else
{
return database.Table<User>().First();
}
}
}
public int SaveUser(User user)
{
lock (locker)
{
if (user.ContactID != 0)
{
database.Update(user);
return user.ContactID;
}
else
{
return database.Insert(user);
}
}
}
public int DeleteUser(int contactid)
{
lock (locker)
{
return database.Delete<User>(contactid);
}
}
}
}
Starting with part 3 of your question - where is the database file? - it's here:
var DBFileName = "backend.db3";
string DocumentPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
That equates to:
/data/data/[your.package.name]/files/backend.db3
For the first part of your question, to check whether the database has been created, just check whether the file exists:
public static bool DBExists()
{
string DocumentPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var path = Path.Combine(DocumentPath, "backend.db3");
return File.Exists(path);
}
Accessing the file there is somewhere between difficult and impossible without a rooted device. You're not supposed to be able to access files there - only your app can access them. It's a safety measure.
Your application doesn't have any trouble accessing the database file, though, so you can implement a method in your application to copy it somewhere more accessible (e.g. the Downloads directory).
Put this in your Android project:
public static void CopyDBToDownloadsDirectory()
{
var path = System.IO.Path.Combine(
Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath,
"backend.db3");
string DocumentPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var safePath = Path.Combine(DocumentPath, "backend.db3");
File.Copy(safePath, path, true);
}
Call it to create a copy of the database you can readily access on the phone's built-in file browser.
So, for part 2 of the question, whether a transaction succeeded or failed, you can either run queries against your database in code to check, or open a copy of the database file in a GUI and browse the data.

C# Ninject: How to inject dependency depending on field?

A class named Round is a level design in a adventure game.Its filed number indicate which level the player is in. Different level will have different figures to guess. The figures are produced by field FigureFactory.
The question is: using Ninject for dependency injection, how can I set the cooresponding FigureFactory to the variable round, according to the field number? For instance, when field number==1, the cooresponding factory is FigureFactory1, when field number==2, the cooresponding factory is FigureFactory2?
using GuessFigure.Model.Factory;
using Ninject;
using Ninject.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ninject.Planning.Bindings;
namespace GuessFigure.Model
{
class Round
{
private int number=1;
private FigureFactory figureFactory;
[Inject]
internal void SetFigureFactory(FigureFactory figureFactory)
{
this.figureFactory = figureFactory;
}
public int[] GetCurrentRoundFigures()
{
return figureFactory.Produce(number);
}
}
//this not work, help please
class RoundModule : NinjectModule
{
public override void Load()
{
Bind<FigureFactory>().To<FigureFactoryRound1>().When(request=>request.ParentRequest.Target.Type.GetField("number").Equals(1));
Bind<FigureFactory>().To<FigureFactoryRound2>().When(request => request.Target.Type.GetField("number").Equals(2));
Bind<FigureFactory>().To<FigureFactoryRound3>().When(request => request.Target.Type.GetField("number").Equals(3));
Bind<FigureFactory>().To<FigureFactoryRound4>().When(request => request.Target.Type.GetField("number").Equals(4));
Bind<FigureFactory>().To<FigureFactoryRound5>().When(request => request.Target.Type.GetField("number").Equals(5));
}
}
}
Factory Method Pattern implementation:
using System;
namespace GuessFigure.Model
{
abstract class FigureFactory
{
protected int figureNumber;
public FigureFactory(int figureNumber)
{
this.figureNumber = figureNumber;
}
internal int[] Produce()
{
int[] figureArray = new int[figureNumber];
for (int i = 0; i < figureNumber; i++)
{
figureArray[i] = Algorithm(i + 1);
}
return figureArray;
}
abstract protected int Algorithm(int inputNumber);
}
}
Concrete Factory(there are still some like this);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GuessFigure.Model
{
class FigureFactoryRound1 : FigureFactory
{
public FigureFactoryRound1(int figureNumber) : base(figureNumber)
{
}
protected override int Algorithm(int inputNumber)
{
return inputNumber;
}
}
}
class FigureFactoryRound3 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GuessFigure.Model.Factory
{
class FigureFactoryRound3 : FigureFactory
{
public FigureFactoryRound3(int figureNumber) : base(figureNumber)
{
}
protected override int Algorithm(int inputNumber)
{
return (int) Math.Pow( inputNumber,2) ;
}
}
}
class FigureFactoryRound4 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GuessFigure.Model.Factory
{
class FigureFactoryRound4 : FigureFactory
{
public FigureFactoryRound4(int figureNumber) : base(figureNumber)
{
}
protected override int Algorithm(int inputNumber)
{
return (int)Math.Pow(inputNumber, 3);
}
}
}
Usage:
IKernel kernel = new StandardKernel(new RoundModule());
Round round = new Model.Round();
round.SetFigureFactory(kernel.Get<FigureFactory>());
int[] array=round.GetCurrentRoundFigures();

NSubstitute Checking received calls don't work

Hey guys im new with the NSubstitute framework. I'm trying to test some of my classes, but when i use NSubstitute to check received calls it says received no matching calls.
I'm trying to test if the method Tick() is receiving update() from track class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ATM_System.Event;
using ATM_System.EventDetection;
using ATM_System.Region;
using ATM_System.Track;
namespace ATM_System
{
public class ATM
{
private List<ITrack> _tracks;
private IRegion _region;
private List<IEventDetection> _eventdetects;
private List<IEvent> _events;
public ATM()
{
_tracks = new List<ITrack>();
_region = new Region.Region(100000,100000); //could be changed by user
_events = new List<IEvent>();
_eventdetects = new List<IEventDetection>();
}
public void Tick()
{
// update track positions
foreach (var track1 in _tracks)
{
track1.update();
}
//check for events
foreach (var detector in _eventdetects)
{
_events.AddRange(detector.DetectEvent(_tracks));
}
//handle events and output
foreach (var event1 in _events)
{
event1.HandleEvent();
event1.LogEvent();
}
}
public void IncomingTrack(ITrack track)
{
//add incoming track
_tracks.Add(track);
}
}
}
TEST FILE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ATM_System.Event;
using ATM_System.EventDetection;
using ATM_System.Track;
using NUnit.Framework;
using NSubstitute;
namespace ATM_System.Tests.Unit
{
[TestFixture]
class ATMUnitTests
{
private ATM _uut;
private ITrack _track;
private IEvent _event;
private IEventDetection _eventDetection;
[SetUp]
public void Setup()
{
_track = Substitute.For<ITrack>();
_event = Substitute.For<IEvent>();
_eventDetection = Substitute.For<IEventDetection>();
_uut = new ATM();
}
[Test]
public void Tick_UpdateTracks_TracksUpdated()
{
_uut.Tick();
_track.Received().update();
}
}
}
You forgot to include _track in notification receivers. It simply hasn't subscribed to event and as a result is not notified. To fix simply call your IncomingTrack method:
[Test]
public void Tick_UpdateTracks_TracksUpdated()
{
_uut.IncomingTrack(_track);
_uut.Tick();
_track.Received().update();
}

using variables from another file .cs

I have a project in c# winforms, with a file called: PublicSettings.cs (this file is within a folder called: Class) where I have a variable.
Now, I want to use that variable from another file within the same project.
PublicSettings.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LVSetup.Class
{
class PublicSettings
{
private string _ConnStr = "Connection";
public string ConnStr
{
get
{
return this._ConnStr;
}
set
{
this._ConnStr = value;
}
}
}
}
I want to use the variable ConnStr in the file: frmLogin.cs
frmLogin.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LVSetup.Class;
namespace LVSetup
{
public partial class frmLogin : Form
{
public frmLogin()
{
InitializeComponent();
}
private void btnEnter_Click(object sender, EventArgs e)
{
string a = PublicSettings.ConnStr;
}
}
}
But there is no ConnStr within PublicSettings, just (Equals and ReferenceEquals)
What could be wrong here?
You need to make this field static in order to access it without creating a class instance. Or create and instance. What suites the best depends on the logic that you want to apply for this class and how it will be used later.
Instance approach
private void btnEnter_Click(object sender, EventArgs e)
{
var settings = new PublicSettings();
string a = settings.ConnStr;
}
Static field approach
class PublicSettings
{
private static string _ConnStr = "Connection";
public static string ConnStr
{
get
{
return _ConnStr;
}
set
{
_ConnStr = value;
}
}
}
For a connection string, I would either use a Configuration file (app.config) or make the property a static read-only property (since there's often no reason to change a connection string at run-time):
class PublicSettings
{
public static string ConnStr
{
get
{
return "Connection";
}
}
}

Selenium Nunit addin install exception

I don't have enough rep to comment, so I am posting a question here. I read this question Get list of failing tests from Nunit. I am trying to implement the nunit addin, I used this code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using NUnit.Core.Extensibility;
namespace NunitAddin
{
[NUnitAddinAttribute(Type = ExtensionType.Core,
Name = "addin",
Description = "addin")]
public class NunitAddin : IAddin
{
public bool Install(IExtensionHost host)
{
IExtensionPoint listeners = host.GetExtensionPoint("EventListeners");
if (listeners == null)
return false;
listeners.Install(this);
return true;
}
public void TestStarted(NUnit.Core.TestName testName)
{
}
public void TestFinished(NUnit.Core.TestResult result)
{
}
public void RunStarted(NUnit.Core.TestName testName)
{
}
public void RunFinished(NUnit.Core.TestResult result)
{
}
public void UnhandledException(Exception exception)
{
}
public void TestOutput(NUnit.Core.TestOutput testOutput)
{
}
}
}
But when I call it using
var addin = new NunitAddin.NunitAddin();
var a = addin.Install(CoreExtensions.Host);
I get an error
NunitAddin.NunitAddin is not {0} extension point
on
listeners.Install(this);
Does anyone know how to solve this problem?
Never mind, issue solved. Just a stupid mistake, I had NunitAddin : IAddin instead of NunitAddin : IAddin; EventListener

Categories

Resources