jag skulle behöva plugga på lite om generics i dao sammanhang men får inte fram nån vettig googling.
det jag vill uppnå är att kunna ha 1 dao-interface som innehåller mina dao:s.
allt är sedan mappat genom nhibernate.
sen vill jag kunna skicka in ex. en produktklass in i interfacet för att spara den i databasen.
jag har sett vissa exempel på detta men det är så svårt att förstå när man bara skrollar radvis med kod.
nån som läst nån bra artikel eller så om detta? :D
Du vill alltså få fram en typ av ActiveRecord-tänk? Isåfall är ActiveRecord fårn CastleRecord kanske ett alternativ. Annars bör det väll inte vara så svårt att göra ett generiskt dao utan den hårda kopplingen mellan domän och persistent som AR skapar.
public interface IGenericDao<T> : IDisposable
{
/// <summary>
/// Gets an object by id
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
T GetObjectById(Guid Id);
/// <summary>
/// Saves a new object
/// </summary>
/// <param name="objectToSave"></param>
/// <returns></returns>
T SaveNewObject(T objectToSave);
}
public class NHibernateGenericDao<T> : NHibernateDaoBase, IGenericDao<T>
{
/// <summary>
/// Gets an object by Id
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public T GetObjectById(Guid Id)
{
try
{
ICriteria criteria = Session.CreateCriteria(typeof(T));
criteria.Add(Expression.Eq("Id", Id));
return criteria.UniqueResult<T>();
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Saves a new object to the database
/// </summary>
/// <param name="objectToSave"></param>
/// <returns></returns>
public T SaveNewObject(T objectToSave)
{
ITransaction tx = null;
try
{
tx = Session.BeginTransaction();
Session.Save(objectToSave);
tx.Commit();
}
catch (Exception)
{
if (tx != null)
tx.Rollback();
throw;
}
return objectToSave;
}
}
Sen får du väll bygga på fecthingstrategies-möjligheter etcetera
Tack erka! Det var lite lagomt mycket kod att ta in. :bire
Nu ska jag bara försöka få in lite villkor och sorteringar i detta så blir det riktigt bra! :)
Det är ju ett DAO, därav namnet, förstår inte hur du menar att det skär sig? Jag vill inte ha den hårda kopplingen mellan repo och mina domänobjekt, seperation of concerns. Så jag håller med författaren och gillar ett interface / dao approach.
Jag anropar inte dao direkt utan kommunicerar alltid genom ett service interface. Och på det viset får jag en tydligare ingång för olika delar av min applikation, ett service interface kan göra saker i flera iolika daos. På det viset tydligare, men utan en så hård koppling som repo skulle ge
public interface IGenericDao<T> : [B]IDisposable[/B]
Har själv funderat på att låta mina DAO:s implementera IDisposable. Antar att du har implementationen av "Dispose" i NHibernateDaoBase? Det är i alla fall så som jag tänkt och sedan stänga mitt ISession-objekt etc.
Anledningen till detta är för jag ska skulle vilja kunna använda min DAO i stil med:
using (IUserDao userDao = daoFactory.GetUserDAO())
{
...
userDao.MakePersistent(user);
...
}
Vanligast är väll session per request, men även där har du ju lite olika val, du kan ju implementera det som att den flushar sessionen först när requesten tar slut så att säga, eller att det sker efter varje dao. Så att du antingen bara gör det du går in för att göra via dina daos eller att objekt som råkas uppdateras på andra ställen, kanske i din codebehind (eller vad du nu har) automatiskt sparas ner vid flusch.
Ett service interface kan göra saker i flera iolika daos. På det viset tydligare, men utan en så hård koppling som repo skulle ge
Har du lust att visa ett mindre exempel på hur det kan se ut? Hämtar du dina DAO:s från en IoC-container? Har kollat lite på Castle Windsor men är lite osäker på hur jag ska göra då jag inte riktigt får ihop helheten. Visa gärna i ett flöde (lager för lager). :)
Har själv funderat på att låta mina DAO:s implementera IDisposable. Antar att du har implementationen av "Dispose" i NHibernateDaoBase? Det är i alla fall så som jag tänkt och sedan stänga mitt ISession-objekt etc.
Nu använder jag inte NHibernate så jag kan vara ute och cykla, men vad i dina DAO objekt kräver att du implementerar IDisposable. Har det med NHibernate att göra? För annars så ser jag inte någon anledning att implementera IDisposable på "vanliga" DAO objekt. De förstörs ändå själv av GC när de inte används längre
Antagligen av samma anledning som alla objekt som använder en resurs är disposable, dvs att det är god ton att fimpa resurser när man är klar med dem, och inte vänta tills nästa gång GC:n behagar gå igång? :)
Vad är best practice när det gäller fetchmode?
Jag tänkte att man kan ha en property som innehåller en modeklass men då får jag inte med propertyn eftersom ett interface inte kan innehålla medlemmar.
Så, hur stuvar jag om detta?
public interface IGenericDao<T> : IDisposable
{
[B]FetchParam FetchParam;[/B] error!!!
}
public class NHibernateGenericDao<T> : NHibernateDaoBase, IGenericDao<T>
{
/// <summary>
/// Setting fetchtype on collections
/// </summary>
private FetchParam fetchParam;
public FetchParam FetchParam
{
get { return fetchParam; }
set { fetchParam = value; }
}
public T GetObjectById(object value)
{
try
{
ICriteria criteria = CurrentSession.CreateCriteria(typeof(T));
criteria.Add(Expression.IdEq(value));
if (fetchParam != null)
criteria.SetFetchMode(fetchParam.Name, fetchParam.Mode);
return criteria.UniqueResult<T>();
}
catch (Exception)
{
throw;
}
finally
{
CloseSession();
}
}
}
public class FetchParam
{
private string name;
private FetchMode mode;
public string Name
{
get { return name; }
set { name = value; }
}
public FetchMode Mode
{
get { return mode; }
set { mode = value; }
}
public FetchParam()
{
}
public FetchParam(string name, FetchMode mode)
{
this.name = name;
this.mode = mode;
}
}
FetchMode kan du lika väll specificera på dina mappningsfiler, det du gör i hql eller criteria overridar det dock. Använder du Lazy Load? FetchMode Eager eller Select är bra att använda just pågrund av problemen med N+1.
FetchMode kan du lika väll specificera på dina mappningsfiler
Mm, jag har default specat i mappningsfilen och nästan alla collections är specad lazy.
Så om jag vill ladda valda collections till ett objekt så behöver jag overrida via SetFetchMode. Propertyn IList<FetchParam> FetchParams (ändrat från FetchParam) fixar tricket åt mig och jag kan ladda de collections jag vill! :)
Dock har jag nu stött på ett problem som ni kanske kan förklara!
Jag har NHibernateGenericDao<T> i ett eget assambly: BaseDao.
Sen har jag ex. ProductDao i ett annat assambly som ärver ovan.
Om jag sedan kör ex. denna kod i aspx.cb
ProductDao pDao = new ProductDao();
Product p = new Product();
p.Name = "foo";
pDao.Save(p);
så får jag: The type 'BaseDao.NHibernateGenericDao`1<T0>' is defined in an assembly that is not referenced. You must add a reference to assembly 'BaseDao, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
Webprojektet har bara en referens till ProductDao.
Hur undviker jag att behöva lägga till en referens från webprojektet till BaseDao?
Antagligen av samma anledning som alla objekt som använder en resurs är disposable,
Är det NHibernate som är resursen i det fallet då som måste disposas. Så i DAO's Dispose-metod så gör man en dispose på Nhibernates objekt?
- M
NHibernate-session (databasanslutningen) är resursen. När man är klar med användingen av DAO:n, så stänger/lämnar man tillbaka anslutningen till connection-pool:en. Det var i alla fall min tanke, men det hela.
262 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e