class & method in C#, is this a good approach? - c#

I am trying to build a class that interacts with the database in my asp.net web application. I need your opinion on how to design it, here's an example of what I have in mind
public class Person
{
int personId;
string name;
string lastName;
public int PersonId
{
get { return personId; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public Person()
{
}
public static void Save(Person p)
{
//datalayer here
//save the person class
}
public static Person GetPerson(int person_id)
{
//datalayer here
//get the person from database and return a person class
Person p = new Person();
p.personId = 10;
p.name = "Alex";
return p;
}
}
So that i can use the database methods without having to instantiate the class:
Person p = Person.GetPerson(19);
p.Name = "Alex...";
Person.Save(p);
I appreciate your help.

Use Automatic proerties because your private fields does the same in your code.
I think, Save is an Operation which can be done on an object of Person Entity. So i wont keep it as a Static method. I would move your Save code as a method of the Person object. So that i will call it like obj.Save(). To load the data, I would use an overloaded version of my class constructor.
public class Person
{
int personId;
public int PersonId
{
get { return personId; }
}
public string Name { set;get;}
public string LastName { set;get;}
public Person() {}
public Person(int person_id)
{
//call to datalayer here
//get the person from database and return a person class
personId = 10;
Name= "Alex"; // set the public property value here
}
public bool Save()
{
//datalayer here
//save the person class and return
// true/false /or new ID (change return type)
}
}
And when calling,
Person p = new Person(19); //get existing person
p.Name = "New Name";
p.Save();
EDIT : Another (better) approach is to keep your entity classes as simple POCO's. that means no data acccess / BL code there. It will simply look like
public class Person
{
public int ID { set;get;}
public string Name { set;get;}
}
And have a Repository which does the data operations for you. So your repository may have methods like this
public interface IRepository
{
Person GetPerson(int id);
bool SavePerson(Person person);
}
You may implement this Interface in a class to do your Data Access operations
public class Repository:IRepository
{
//implementation of your DA methods here
}
Now you may call it from different layer(business layer) like this
IRepository repo = new Repository();
var person=repo.GetPerson(19);
person.Name="Updated Name";
repo.Save(person);

I like the persistance ignorance thing: What are the benefits of Persistence Ignorance?)
In that case you should move the Save method to another class so the entity doesnt contain any information how it should be persisted.

What you're after is the factory method pattern for the objects, and the repository pattern for the data access code. I can't explain it nearly as well as the articles, so instead I'll go over the basic ideas and provide some examples.
The goal is to divide up your code base in to layers that deal with one specific type of concern, such as communicating with the user (UI), holding and validating data within the application (business classes / model), or managing data persistence (data access). Keeping these areas neatly divided makes it easier to maintain and debug code or develop in parallel. There are other benefits as well, such as facilitating architecture across multiple physical machines, but that's outside the scope of the question.
The basic structure:
Fetching conceptual progression:
UI -> Person Factory -> Person class -> Repository -> Database
Saving conceptual progression:
UI -> Person class -> Repository -> Database
Person class structure, with explanatory comments inside:
public class Person
{
// various properties & methods
// Constructor access is restricted to control how the class gets consumed.
// All instance management must go through the factories.
protected Person() { /* stuff */ }
// Person factory implementation. It's done inside the Person class so that
// tight control can be kept over constructor access.
// The factory is what gives you your instances of Person.
// It has defined inputs and outputs, as well as more descriptive
// names than constructor overloads, so consumers know what to expect.
// It's also a place to put scaffolding code, so you can avoid doing
// things like setting properties every time you fetch an instance.
// The factory takes care of all the object initialization and returns
// an instance that's ready for use.
public static Person GetPerson(int id)
{
Person p = new Person();
// here you call the repository. It should return either a native
// data structure like DataReader or DataTable, or a simple DTO class
// which is then used to populate the properties of Person.
// the reason for this is to avoid a circular dependency between
// the repository and Person classes, which will be a compile time error
// if they're defined in separate libraries
using(PersonRepository repo = new PersonRepository())
{
DataReader dr = repo.GetPerson(id);
p.FillFromDataReader(dr);
}
return p;
}
protected void FillFromDataReader(DataReader dr)
{ /* populate properties in here */ }
// Save should be an instance method, because you need an instance of person
// in order to save. You don't call the dealership to drive your car,
// only when you're getting a new one, so the factory doesn't do the saving.
public void Save()
{
// Again, we call the repository here. You can pass a DTO class, or
// simply pass the necessary properties as parameters
using(PersonRepository repo = new PersonRepository())
{
this.Id = repo.SavePerson(name, address);
}
}
}
Now, the repository code:
// This class implements IDisposable for easy control over DB connection resources.
// You could also design and implement an IRepository interface depending on your needs.
public class PersonRepository : IDisposable
{
private SqlConnection conn;
public PersonRepository()
{
// in here you initialize connection resources
conn = new SqlConnection("someConnectionString");
}
public void IDisposable.Dispose()
{
// clean up the connection
conn.Dispose();
}
// The instance methods talk to the database
public int SavePerson(string name, string address)
{
// call your stored procedure (or whatever) and return the new ID
using(SqlCommand cmd = conn.CreateCommand())
{
// stuff
return (int)cmd.Parameters["myOutputIDParameter"].Value;
}
}
public DataReader GetPerson(int id)
{
// call your stored procedure (or whatever) and return the fetched data
using(SqlCommand cmd = conn.CreateCommand())
{
// stuff
return cmd.ExecuteReader();
}
}
}
Finally, here's what you'd do at the UI level:
Person joe = Person.GetPerson(joeId);
// stuff
joe.Save();

You are doing right but you can also use automatic properties for you class. It may save some of your time.
eg.
public class Person
{
public int PersonId { get; set;}
public string Name { get; set;}
public string LastName { get; set;}
public Person()
{
}
}

Related

How do I define the signature of a function that must be implemented by instances of a class?

Say I have a class Book:
public class Book{
public string Title {get; set;}
}
I want every book to have a Read function that returns a string and accepts a page number - but the internals will be different for every book (poor example, I know). How do I define the signature of a function that must be implemented by instances of this class?
Something like this:
public class Book{ // need to make this abstract?
public string Title {get; set;}
public abstract string Read(int pageNum);
}
// I want to define instances that define their own behavior...
public static Book It => new Book(){ // can't create instance of abstract...
Title = "It",
Read... // what do I do here?
}
My main concerns are:
Keeping things as simple as possible. Implementing interfaces under abstract classes works, but it gives me n*2 things to worry about as I add more instances.
I will need to add a large number of these custom functions - passing Funcs through constructors seems unwieldy.
In practice - this is used to define a Tenant. The Tenants are defined in-memory, and have many static properties like domain, name, adminEmail, etc. Those are tenant-specific properties... but now I am trying to implement tenant-specific behaviors - like GetBooks or FilterUsers. I would like to keep implementation as simple as humanly possible. Right now I have "If TenantA, do this, else if tenantB, do this..." sprinkled throughout my code. I'm trying to consolidate all tenant-specific logic and detail in one place - on instances of the Tenant class.
Further examples of Tenant specific behavior - you have a SaaS forum software. On the homepage of Forum A, you GetCoverPhoto by reading from a static file. On the homepage of Forum B, you GetCoverPhoto by reading from a blog homepage. Currently, I say "If Forum A, do this, else If Forum B, do this". This is the type of tenant-specific behavior that I want to define on the Tenant object, instead of in code. I don't want any tenant-specific code in my core logic.
Is there a simple feature/pattern in the C# language that will achieve this?
What NineBerry said is very valid.
There is one other way of accomplishing what you might want. If you want to dynamicly inject the read method implementation into a Book. This can be seen as strategy pattern. And can be done as interfaces like in many languages, but in simplest form in C# it can be done by delegates. Example:
public class Book{
Func<int, string> readFunc;
public Book(Func<int, string> readFunc)
{
this.readFunc = readFunc;
}
public string Title {get; set;}
public string Read(int pageNum) { return readFunc(pageNum); }
}
Then use it as:
public static Book It => new Book(){
Title = "It",
Read = (pageNum) => ... // Do actual reading in delegate
}
EDIT: With more detail on requirements (but still not everything is obvious) I would do something like this:
public class Tenant
{
// core things go here
public Extensions Extensions { get; }
}
public class Extensions : IEnumerable<IExtension>
{
private IList<IExtension> list = new List<IExtension();
private Tenant { get; set; }
public Extensions(Tenant tenant)
{
Tenant = tenant;
}
public void Add(IExtension extension)
{
extension.Tenant = Tenant;
list.Add(extension);
}
}
public interface IExtension
{
Tenant { get; set; }
// shared interface of extensions if any can be abstracted
}
public interface ICoverPhotoExtension : IExtension
{
Photo GetCoverPhoto();
}
public class FileCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from file
}
public class BlogCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from blog
}
usage:
Tenant tenant; // initialized somehow
var coverPhotoExtension = tenant.Extensions.FirstOrDefault<ICoverPhotoExtension>();
Photo photo = coverPhotoExtension?.GetCoverPhoto();
public Interface IBook{
string Title {get; set;}
func<int,string> ReadPage
}
Use containment over inheritance. In the interface example above there is a function in every book that implements IBook that will return a string for that page.
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return GetText(pagenumber);
}
public string GetText(int pageNumber){
//read the page text by number here.
}
}
I would make GetText an extension method similar to this, so each book doesn't need to implement GetText itself.
public static class XBook{
public static string GetText(this IBook book, int pageNumber){
///do the work here and returng string
}
}
To use the Extension method concept:
using XBook;
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return this.GetText(pagenumber);
}
}
There are more ways to do this... for now, give it a try.
Having different instances of a class implement functions differently is not possible. Instead, you inherit a new class where you implement the separate behaviour.
public abstract class Book
{
public string Title {get; set;}
public abstract string Read(int pageNum);
}
public class ITBook : Book
{
public override string Read(int pageNum)
{
// Code here
}
}
Then use the class like this:
public static Book It => new ITBook()
{
Title = "It",
}
You could use a property of a delegate type in the Book class to use different functions in different instances of the Book class, but these functions would not have access to the other properties and methods of the instance they would be used by.

Converting a Method into a more Generic or Interfaced-based Method - Design Advice

I've searched for similar questions/problems on here and can't seem to find a solution that fits.
I currently have a class that it's constructor has one parameter which in turn calls a method which does not have any parameters but instantiates two objects. In the method, DoWork(), the requirements have changed, so I will need to handle other classes/objects, e.g. Building, Vehicle, etc. I am seeking advice on what would one recommend to take in these other objects, e.g. interfaces, generics, etc?
public class Project
{
public Person Person { get; set; } // will need to handle other classes as well
public String Task { get; set; }
// ctor
public Project(string task)
{
Task = task;
DoWork(); // should I handle this method here?
}
// current method
private void DoWork()
{
var work = new Work(this.Task);
Person = new Person(); // this instance of Person could be other objects as noted
Person.Job = work.Assignment;
Person.Site = work.Site;
...
If your classes Person, Building, Vehicle etc. shares some behavior, and the DoWork method only uses this behavior, polymorphism (either abstract class or interface) would be the best solution.
public MyData Data { get; set; }
void DoWork() {
Data.DoStuff();
}
In the case it wouldn't work, you can overload your DoWork method to do different stuff based on the instance, but this would require getting the instance as a parameter.
void DoWork(Person p) {
...
}
void DoWork(Building b) {
...
}
Otherwise, you can either use generics or polymorph on the Object class (and in both cases, deal with unwanted/unexpected types).
if (obj is Person)
...
else if (obj is Building)
...
else
throw new Exception();
If you want to retain the current structure and simply use a generic type instead of always creating a Person, a very straightforward refactoring looks something like this.
Create an abstract base class for the resource (a person, building, vehicle) required for a project.
public abstract class Resource
{
public virtual Assignment Job { get; set; }
public virtual Site Site { get; set; }
}
Create your concrete classes.
public class Person : Resource
{
public Person()
{
}
}
public class Building : Resource
{
public Building()
{
}
}
Now you can make your Project class accept a generic type T instead of Person. In this example, T must be some derived class of Resource and must support a parameterless constructor.
public class Project<T> where T : Resource, new()
{
public T Resource { get; set; } // will need to handle other classes as well
public String Task { get; set; }
// ctor
public Project(String task)
{
Task = task;
}
// current method
public void DoWork()
{
var work = new Work(this.Task);
Resource resource = new T(); // this instance of Person could be other objects as noted
resource.Job = work.Assignment;
resource.Site = work.Site;
// ...
}
}
You create your projects and do work like this.
Project<Person> personProject = new Project<Person>("MyTask");
personProject.DoWork();
Project<Building> buildingProject = new Project<Building>("MyBuildingTask");
buildingProject.DoWork();
You should not call DoWork from the constructor as shown in your code sample. Create the instance first, then call the method.

Avoiding logic in setter properties when using NHibernate

I have a design like this:
public class Employee {
//...
}
public class Company {
private IList<Employee> _employees;
public IList<Employee> Employees {
get { return _employees; }
set {
if (_employees == value) {
return;
}
_employees = value;
//Some logic here. Eg:
//Raise PropertyChanged
//Iterate over the new values to suscribe to some events, etc.
}
}
}
when I try to do something like:
var employees = session.Query<Company>().Fetch(x => x.Employees).ToList();
it throws a LazyInitializationException:
illegal access to loading collection
The only workaround I've found is moving the logic to a method, making this method public (and virtual) and calling the method for every instance in employees, but I don't like that since I will be calling that method from my repositories.
Any ideas?
You are mixing fetching data from the database with control logic. I'd recommend fetching the data into simple value objects. Then transform it into your Company and Employee logic-laden classes afterwards. That way you separate data entities from functionality based on that data.
In Nhibernate you collection class should not be exposed to the out side world. Your typical domain would look like this
public class Company
{
public virtual String Id { get; set; }
public virtual ICollection<Employee> Employees { get; protected set; }
public Company()
{
Employees = new List<Employee>();
}
public void AddEmployee(Employee employee)
{
if (Employees.Contains(employee))
return;
Employees.Add(employee);
employee.Company = this;
}
public void RemoveEmployee(Employee employee)
{
if (!Employees.Contains(employee))
return;
Employees.Remove(employee);
}
}
public class Employee
{
public virtual String Id { get; set; }
public virtual String FullName { get; set; }
public virtual Company Company { get; set; }
}
I agree with the first responder who said to user view models and INPC those, but if you want to bind directly to your domain objects, you can inject INPC directly into your domain objects.
Please see this original post from Ayende and this updated one from Ricardo
I guess you are using 'property' as collection accessor in your mapping, if so the behavior you describe is the expected one when your code tries to modify the collection.
If you want to use that pattern in your domain model, you should change collection accessor to 'field' (with the appropriate naming strategy), in order to tell NHibernate to set the backing field '_employees' and not the property 'Employees'.
This will not trigger your code that tries to access the collection anymore.

Lazy loading or proxy pattern in my library

Hi i'm writing a simple ORM DLL. The library works fine and i would like add some addone - Lazy Loading.
But i don't know how to implements that. I have one proposition.
In my orm (i have creator but never mind) User should create DB class who implements IMapper and set mapper class.
Somethink linke this.
public class Person
{
public virtual string Name {get;set;}
public virtual int Age {get; set;}
}
public class DataBase : IMapper
{
MapperSet<Person> Persons = new MapperSet<Person>();
}
If we have that class, and setup connectionString, we can take the data from DB. It's very similar to Entity Framework
Person p = Persons.Single(x=>x.Name == "John");
In that moment, i will check the all properties in mapping class and if are virtual then not return a that class, but Lazy Loading class.
I think out one conception. Not return (in that example) Person class but the class who extends Person class, and override all properties.
public class PersonReturn : Person
{
//here i must create a method who really take the data from db
private string Query = "SELECT TOP(1) FROM Person WHERE Name = 'John'";
private Execute()
{
p = (Person)Db.TableToObject(Query);
}
Person p;
public override string Name
{
get
{
if(p == null)
p = Execute();
return p.Name;
}
set {}
}
//same
public override int Age {get; set;}
}
User shouldn't see any change with using that class (only in debug it maybe see other class) it's should work as magic :P
My questions are :
1. How is implement Lazy Loading in for example Entity Framework, anybody know ?
2. Is simpler way from my proposition ? In my idea i must use TypeBuilder and Emit with IL source code - i hear it's problems with properties
they aren't be use in normaly way.
Use Castle.DynamicProxy (same proxy that nhibernate uses)
Lazy loading is implemented by generating inheritor at runtime and override all methods.
public class A
{
virtual protected string name { get; set; }
}
public interface IInterceptor
{
object Invoke(MethodInfo method, params object[] arguments);
}
public sealed class AProxy : A
{
static private readonly MethodInfo getname = typeof(A).GetProperty("name", ...).GetGetMethod(true);
static private readonly MethodInfo setname = typeof(A).GetProperty("name", ...).GetSetMethod(true);
private readonly IInterceptor interceptor;
public AProxy(IInterceptor interceptor)
{
this.interceptor = interceptor;
}
override protected string name
{
get { return this.interceptor.Invoke(AProxy.getname); }
set { this.interceptor.Invoke(AProxy.setname, value); }
}
}
Proxy factory have to to
return new AProxy(custominterceptor);
custominterceptor must take id of your entity and in first usage instantiate A, query database to populate A and delegate call to A.
AProxy must be generated (postbuild or at runtime using TypeBuilder)

C# OOPs architecture problem

I am facing a class resolution issue while trying to make my architecture flexible. To make it simple, consider the following example:
I have four tiers: UI, BL, Common and DAL
I have a base class in my BL layer as defined below:
public class User
{
private UserDTO _d;
public User()
{
_d = new UserDTO();
}
public User(UserDTO d)
{
_d = new UserDTO(d);
}
public UserDTO D
{
get { return _d; }
set { _d = value; }
}
//static method (I cannot make it non-static due to some reasons)
public static User GetUser()
{
User user = new User(Provider.DAL.GetUser());
return user;
}
}
The DTO is defined as:
public class UserDTO
{
public int ID;
public UserDTO()
{
}
public UserDTO(UserDTO source)
{
ID = source.ID;
}
}
My DAL is defined as (it returns a DTO not a business object):
public static UserDTO GetUser()
{
UserDTO dto = new UserDTO();
dto.ID = 99;
return dto;
}
Now, I want to "extend" my code so that I can have one more field in my User table: Name. So I create a derived DTO class as:
public class MyUserDTO : UserDTO
{
public string Name;
public MyUserDTO()
{
}
public MyUserDTO(MyUserDTO source)
{
Name = source.Name; //new field
base.ID = source.ID;
}
}
Then, I create a derived User class as:
public class MyUser : User
{
public MyUser()
{
this.D = new MyUserDTO();
}
}
And I create my own custom DAL provider with this method:
public static UserDTO GetUser()
{
UserDTO dto = new MyUserDTO();
dto.ID = 99;
((MyUserDTO)dto).Name = "New Provider Name";
return dto;
}
Now when I access this MyUserDTO object in my BL, it loses resolution:
User.GetUser(DAL.Provider.GetUser())
and in the UI, I dont get the properties in the MyUserDTO.
Is there a method which can help me get those properties in the UI layer, even after I call the static User.GetUser() method (which will in turn call my custom provider returning a MyUserDTO object)?
Thanks,
You don't inherit from a class to add in new data, only inherit if your new class is going to extend the behaviour of your old class.
Give your UserDTO a Name-Value collection to hold its data and populate that. Then you won't have an issue.
You're not getting the derived behaviour because the static method in the user class can't be overriden by the MyUser class.
You should remove the static method (I know you've indicated you can't), but really you should.
Try to extract the creation of your users in another object (factory, repository,...)
As others have mentioned, the problem is with the static method.
I would also suggest using generics or dependency injection to clean up your parallel object hierarchy. You don't want that duplication.
Instead of having a set of almost-identical 'User' and 'MyUser' classes, that have the same hierarchy, just do something like User and plug in the UserDTO type that you want.
If you refactor and remove the object hierarchy duplication, it may make it easier to see a good solution to get around the problem with the static GetUser().
From what I can see it looks like User.GetUser() will return a User object, not a MyUserDTO object, which is why you don't get those extra fields. The DAL layer needs to abide by the contract it was written against. There are a handful of ways you could go about solving this, although some are more "right" than others.
You could cast the object you get out of User.GetUser to the appropriate object which would then give you access to the casted object's fields (assuming the object can be cast to that type). I don't really like this solution from a design perspective, but it would work:
MyDTOUser myDtoUser = User.GetUser() as MyDTOUser;
Other people have posted some other examples of ways around this so I won't repeat those here.

Categories