Impossibile ottenere dati dal livello DA. Cosa fare?
Domanda
Mentre dividevo la mia applicazione C # in livelli, ho risolto il problema della dipendenza circolare tra i livelli nel modo seguente:
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.Common;
using SolvingCircularDependency.DA;
namespace SolvingCircularDependency.BO
{
public class MyClass : IPersistent
{
private string _message;
public string Message
{
get { return _message; }
set { _message = value; }
}
public bool Save()
{
return MyClassDA.Save(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace SolvingCircularDependency.Common
{
public interface IPersistent
{
bool Save();
string Message { get;}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.Common;
namespace SolvingCircularDependency.DA
{
public class MyClassDA
{
public static bool Save(IPersistent obj)
{
Console.WriteLine(obj.Message);
return true;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.BO;
namespace SolvingCircularDependency.UI
{
class Program
{
static void Main(string[] args)
{
MyClass myobj = new MyClass();
myobj.Message = "Goodbye Circular Dependency!";
myobj.Save();
Console.ReadLine();
}
}
}
Dai un'occhiata alla classe MyClassDA nel livello DA e all'assembly stesso.
Come può un metodo MyDA.Get () restituire oggetti di tipo MyClass quando il livello di accesso ai dati non è a conoscenza del tipo MyClass.
Se questo design non è efficiente, come posso cambiarlo / modificarlo?
Soluzione
Per quanto posso capire, hai una relazione bidirezionale tra il tuo livello DA e Business. Per risolvere questo problema, ti suggerisco di avere 3 livelli invece di due. Voglio dire che dovresti avere un livello Model che modella semplicemente gli oggetti DB, quindi puoi derivare dalle classi del modello nel tuo livello Business e aggiungere altri comportamenti come il metodo Save.
Ecco cosa intendo:
//Model Layer
public class UserModel
{
public virtual string Firstname{get;set;}
}
//DataAccess Layer
public class UserDao
{
List<UserModel> GetAll();
}
//BusinessLayer
public class UserDomainModel:UserModel
{
public UserDomainModel(UserModel user,UserDao dao)
{
_user=user;
_dao=dao;
}
public override string FirstName
{
get
{
return _user.FirstName;
}
set
{
_user.FirstName=value;
}
public void Save()
{
_dao.Save(_user);
}
}
}
Sto usando un decoratore per combinare Utente e UserDao come oggetto modello di dominio.
Altri suggerimenti
Uno dei motivi per cui le persone eseguono oggetti Ignorant di persistenza (POCO) è evitare questo scenario. Semplicemente non c'è modo per il livello di accesso ai dati di avere un riferimento a una classe di cui non è a conoscenza - è molto meglio che la classe non sia a conoscenza dell'accesso ai dati.
L'unico modo per farlo è implementare Get () sull'utente anziché su UserDA. Puoi fare qualcosa del genere:
public class User {
IGetFromPresistance<User> _userFetcher;
public static IList<User> GetMatching(Specification<User> spec) {
var values = _userFetcher.Find(spec); //Returns a DataRow or IDictionary<string, object>
return new User() {
PhoneNumber = new PhoneNumber(values["phone"].ToString()),
Name = values["name"].ToString(),
};
}
}