-1

While dividing my C# application in layers, I have solved the problem of circular dependency among layers in the following way:

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();
        }
    }
}

alt text

Please take a look at the class MyClassDA in the DA layer and the assembly itself.

How can a MyDA.Get() method return objects of type MyClass when the Data Access layer doesn't know about the MyClass type.

If this design is not efficient, How can I change/modify it?

Community
  • 1
  • 1
user366312
  • 16,949
  • 65
  • 235
  • 452
  • 1
    This is an incredibly poorly worded question. I read your other post but I have no idea what it is you're looking for. Can you reword it stating your problem more specifically? – George Mauer Sep 12 '09 at 19:31
  • I, too, have no clue what it is you're asking. What is the code supposed to represent? I don't see a UserDA class anywhere. What does "interface instances can't be stuff with data retrieved by an SqlDataReader" mean? – Adam Robinson Sep 12 '09 at 19:41
  • Which part are you having a problem with? Do you not know how to do data access at all? – John Saunders Sep 12 '09 at 19:45
  • I could obviously answer "what should I do?" with the snarky answer of "retrieve data and populate an in-memory repository", but I doubt that's helpful. What is the specific issue you're facing? – Adam Robinson Sep 12 '09 at 19:47
  • He's asking how can a UserDA.Get() method return objects of type User when the Data Access layer doesn't know about the User type. Its a fair question, though I think this architecture will cause more trouble than is worth. See my answer below. – George Mauer Sep 12 '09 at 20:00
  • Actually JMSA, you should probably change the text of the question somewhat. It was pretty tough to understand for me too. – George Mauer Sep 12 '09 at 20:02

2 Answers2

1

One of the reasons people do Persistance Ignorant objects (POCO) is to avoid such a scenario. There is simply no way for the data access layer to have a reference to a class that it doesn't know about - it is much better to have the class not know about the data access.

The only way you can really do this is to implement Get() on User instead of on UserDA. You can do something like this:

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(),
    };
  }
}
George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • How should I change the architecture to achieve a better design? – user366312 Sep 12 '09 at 20:07
  • I am a big fan of the way Sharp Architecture does it: http://sharparchitecture.net/ download the files and look for the doc in there - it has a lengthy description of the pattern the process is also described generally in this article: http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx Basically you have a data access object in the DAL with non-static methods like UserDao.GetById(int id) : User and UserDao.Save(User user). The User doesn't know anything about persistence concerns - it ONLY describes the user business object – George Mauer Sep 12 '09 at 20:20
  • Each UserDao is also based on IUserDao. The interface is in the domain layer and the DA layer depends on the Domain (but the Domain does not depend on the DA). If you really need to you can have business objects using an IUserDao and the specific implementation is injected into them from a higher layer. By the way throughout the course of the articles describing this pattern the term DAO and Repository are used somewhat interchangeably though the hardcore DDD guys would argue there is actuall a difference. – George Mauer Sep 12 '09 at 20:23
1

As far as I can understand you have a bidirectional relationship between your DA and Business layer. To solve this problem I suggest that you should have 3 layers instead of two. I mean you should have a Model layer that simply model the DB objects ,then you can derive from model classes in your Business layer and add other behaviors like Save method.

Here's what I mean:

//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);
}
}
}

I'm using a decorator to combine User and UserDao as a domain model object.

Beatles1692
  • 5,214
  • 34
  • 65