My question is related to the bll,dal,interfaces.
My project's constructure more or less like this.
BLL, DAL, OBJ and 3 layer architecture
(As I dont repeat question and codes again,I give the link here)
My question is why should I use interfaces,what is the benefits.and how can apply interfaces based on the project structure which is gaved above.
could u provide link or answers.thank you all
Interfaces allow you to define the behavior without the actual implementation, think of it as a contract.
If you only have one implementation, then an interface is not very useful and is not recommended.
Where interfaces shine, is when you have multiple implementations of the same logic. Say for example the data access layer (DAL), like this:
public interface IPersonRepository
{
Person CreatePerson(string firstName, string lastName, int age);
Person LoadPerson(int personId);
Person SavePerson(string firstName, string lastName, int age);
bool DeletePreson(int personId);
}
Now if you have a SQL Server database, then you could have a repository class that implements the IPersonRepository interface, like this:
public class SqlServerPersonRepository : IPersonRepository
{
// Implement SQL Server specific logic here
}
Let's say you want to support Oracle, as well, then you create an OraclePersonRepository, like this:
public class OraclePersonRepository : IPersonRepository
{
// Implement Oracle specific logic here
}
What is also useful is that you can create a mock person repository (for testing), like this:
public class MockPersonRepository : IPersonRepository
{
// Implement mock logic here
}
Interfaces are useful in a lot of examples. To give you one of the most popular, consider the Repository pattern commonly used for Data Layer implementation.
Let's say I implement my DAL for SQL Server. In the future, my company decides to switch to MySQL. All of my BLL calls to the DAL are now vulnerable to being rewritten/dramatically modified.
If I had used an interface (say IRepository), I could have written SqlRepository, which implements IRepository. I would then have the BLL reference IRepository, using Dependency Injection to give SqlRepository to the BLL at runtime. When the business decided to use MySQL, I can then write MySqlRepository, implement IRepository, and then all of my BLL doesn't have to be rewritten to handle MySQL. In fact, my BLL doesn't even know SqlRepository or MySQLRepository exists. It just communicates via the interface IRepository.
Some other key uses for Interfaces are getting around the lack of multiple inheritance in C#, as well as for some Web Service implementations. I think for your current setup, the example I gave above is one of the more useful demonstrations of the usefulness and power of interfaces.
Definitely look up the Repository Pattern as well as Dependency Injection / Inversion of Control. Once you are comfortable with it, you'll find more and more places to use Interfaces to keep your code as loosely coupled as possible.
Here's a short example of the implementations of IRepository and SqlRepository:
public interface IRepository
{
List<string> GetUserIds();
void CreateUser(string userId);
bool DeleteUser(string userId);
}
public class SqlRepository : IRepository
{
public List<string> GetUserIds()
{
// Provide your implementation of GetUserIds.
// Connect to DB, retrieve data, return
}
public void CreateUser(string userId)
{
// Provide implementation
}
public bool DeleteUser(string userId)
{
// Provide implementation
}
}
Related
Our Asp.net web application is using LINQ-to-SQL (Stored Procs are dragged on dropped on dbml file to create classes) and 3 tier architecture is similar to the one below. I have just created rough methods to give reader proper idea so that he can answer well.
namespace MyDataLayer
{
public class MyDataAccess
{
// global instance of datacontext
MyDataModelDataContext myDB = new MyDataModelDataContext(); (#1)
public void GetUserIDByUsername(string sUserName, ref int iUserID)
{
int? iUserIDout = 0;
// this will make call to SP in SQL DB
myDB.USP_RP_GETUSERIDBYUSERNAME(sUserName, "", ref iUserIDout);
iUserID = (int)iUserIDout;
}
public List<USP_APP_USERDETAILSResult> GetUserDetails(string sUserIDs)
{
// this will make call to SP in SQL DB
return myDB.USP_APP_USERDETAILS(sUserIDs).ToList();
}
...
... // several CRUD methods
}
}
namespace MyBusinessLayer
{
public class SiteUser
{
// global DataAccess instance
MyDataLayer.MyDataAccess myDA = new MyDataAccess(); (#2)
public void GetUserIDByUsername(string sUserName, ref int iUserID)
{
myDA.GetUserIDByUsername(sUserName, ref iUserID);
}
public List<USP_APP_USERDETAILSResult> GetUserDetails(string sUserIDs)
{
// this will make call to SP in SQL DB
return myDA.GetUserDetails(sUserIDs);
}
...
... // several CRUD methods
}
}
namespace MyWebApplication
{
public class BaseWebPage : System.Web.UI.Page
{
// static business layer instance
public static MyBusinessLayer.SiteUser UserBLInstance = new SiteUser(); (#3)
...
}
}
// Index.aspx.cs code fragment
namespace MyWebApplication
{
public class Index : BaseWebPage
{
public void PopulateUserDropDown()
{
// using static business layer instance declared in BaseWebPage
List<USP_APP_USERDETAILSResult> listUsers = UserBLInstance.GetUserDetails("1,2,3");
// do databinding and so on ...
}
...
}
}
Questions
(Ref.#1) Is having global datacontext in DataAccess good approach? yes/no why?
If your suggestion is having datacontext per request what is the best practice for that
(Ref.#2) Is having global DataAccess instance in BusinessLayer good approach? yes/no why?
If your suggestion is having DataAccess instance per request what is the best practice for that
(Ref. #3) Is static business layer instance declared in BaseWebPage good approach? yes/no why?
Best approach to manage life time of BL instance and DL instance in general
We are facing periodic InvalidCastException on production server for a very simple method which works fine if I restart my application from IIS. When this problem is there we can access the same database from SQL Management Studio and can execute same SP
Our prime suspect about this issue is poor DataContext management and I have read many articles on net about managing life time of DataContext but I am now confused about various approach.
That's why I have elaborated my questions so that many in same situation can get clear idea about problem/answer.
(Ref.#1) Is having global datacontext in DataAccess good approach? yes/no why?
Yes.
However, creating it manually inside the dataaccess class means that you can't control the lifetime of the datacontext. Instead, make it then a constructor parameter so that it is injected into the data access
(Ref.#2) Is having global DataAccess instance in BusinessLayer good approach? yes/no why?
Yes. But refer to 1. - make it injectable via the constructor.
(Ref. #3) Is static business layer instance declared in BaseWebPage good approach? yes/no why?
No. Avoid static for complex objects as usually such objects has non-trivial state. And this is when a lot of nasty issues can happen if you share such objects in a concurrent environment.
To summarize.
public class DataAccess {
public DataAccess( DataContext context ) { ... }
}
public class BusinessLayer {
public BusinessLayer( DataAccess access ) { ... }
}
public class MyPage : Page {
...
var ctx = TheDataContext.Current;
var bl = new BusinessLayer( new DataAccess( ctx ) );
}
with data context shared in a request scope:
public partial class TheDataContext {
// Allow the datacontext to be shared in a request-scope
public static TheDataContext Current {
get {
if ( HttpContext.Current.Items["context"] == null )
HttpContext.Current.Items.Add( "context", new TheDataContext() );
return (TheDataContext)HttpContext.Current.Items["context"];
}
}
}
In your sample - your MyDataLayer usually has name Repository. Definitely it is good to have DataContext instance in Repositories and do not try to use them outside. So, only in repositories you will have dependency on Linq-To-Sql, which means that you can create Stub objects for these Repositories and really easy test other parts of your application.
Definitely you should Dispose your Data Context instances, DataContext contains too many objects to keep them alive and let GC to kill them. As you can see you don't create any transaction objects when you are working with DataContextes, so I think that LinqToSql based on idea that you should have everything per transaction (of course you can also try to handle transaction manually, but do you really want to do this?). Disposing datacontextes in methods of Repository is a good approach, because this will not allow you to use cool feature of all ORM frameworks: Lazy Load. If you will try to use Lazy Load - you will like it, but usually it is just one of possible performance degradation cause.
Definitely your should use DataContextes for shorter or the same time of Request, don't try to use LongSession (it is when you trying to keep DataContext for more than one Http Request, it is just pain in ass, nothing else, if you want to read about this, just try to read couple articles about Long Running Session in Hibernate, I tried with nHibernate - don't do this at home ;) ).
I have a vs2010 solution with many project (WPF control library, some business logic etc.)
Currently each library reach the WCF data services using his own Service Reference.
I'm trying to write a new library that will a some kind of a DL to the WCF data service, I want to write it using templates - so I don't need to write the same function to all my entities (~30).
Well I'm getting nowhere..
I started by add a simple Interface like this:
public interface IRepository<T>
{
IQueryable<T> GetAll();
T GetSingle(int id);
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
IQueryable<T> Where(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Update(T entity);
}
I'm trying to implement the interface and I came into issues I have no Idea how to solve
1) in the implementing class how do I tell my context which entity I'm querying
public IQueryable<Region> Where(Expression<Func<T, bool>> predicate)
{
return _context.(something general).Where(predicate);
}
2) Even if I provide the entity
public IQueryable<Region> Where(Expression<Func<T, bool>> predicate)
{
return _context.Region.Where(predicate);
}
I came into casting issues I didn't manage to solve.
well, that's about it.
Thank you
I've been experiencing by the very same problem: it is not possible to declare a WCF contract with open generic types (nor interfaces, by the way). The problem is that this framework does not adhere to some basic good OOP principles and, thus, it causes some frustration to experienced programmers.
For more information about this issue, see the example at msdn.
I have a DAL project, with an entity data model context bound with EF 4.1
I provide methods to access this context through a "Business" project.
My question is the following:
I'm thinking I shouldn't reference the DAL project from somewhere other than the Business project, so my thinking is, I could add "DataContract" interfaces to the Common project I already have, reference this project within the DAL project, extend the partial classes EF has autogenerated for me, inherit the DataContracts corresponding to each of them, and use these DataContracts as the return value of operations in the Business project, thus isolating the DAL project and avoiding to tightly couple it to either the business, or web projects
Is my thinking correct or am I way off?
Update In re-reading my own question I find this kind of hard to follow, here's an example of how I'd do it, with one of the entities in the model:
The entity is:
namespace Application.Website.Main.Common.DataContracts
{
public interface IServerApplication
{
string Id { get; set; }
string ApplicationName { get; set; }
byte MaxAccountsPerUser { get; set; }
bool Enabled { get; set; }
}
}
This would be in the Application.Website.Main.Common project.
In the DAL project, I would reference the Common project, and extend the partial class of the ServerApplication to inherit from that interface, no further changes required.
namespace Application.Website.Main.DAL
{
public partial class ServerApplication : IServerApplication
{
}
}
In the Business project, I would reference both the DAL and the Common projects, and I'd use these DataContracts as return types:
namespace Application.Website.Main.Business.Entities
{
public class ServerApplication
{
public static IEnumerable<IServerApplication> Enabled()
{
var context = HttpContext.Current.GetDataContext();
return context.ServerApplications.Where(a => a.Enabled);
}
}
}
For completeness, this is the GetDataContext() extension method, placed in the DAL project:
public static class HttpContextExtensions
{
internal const string _contextDataKey = "dataContext";
public static EntityDataModelContext GetDataContext(this HttpContext httpContext)
{
if (httpContext.Items[_contextDataKey] == null)
httpContext.Items.Add(_contextDataKey, new EntityDataModelContext());
return (EntityDataModelContext)httpContext.Items[_contextDataKey];
}
}
By the way, where should I be doing the try/catching?
Should that be done on each of the Business-level methods that use the data context?
Or somewhere else?
What would be the best way to handle exceptions at this level?
Update I found a hole in my logic. If I wanted for instance to have a method in the Business class for a given entity, it would either have to be static and/or an extension method to the interface. Like this:
namespace Application.Website.Main.Business.Entities
{
public class MembershipUser
{
public static int GetRequestCount(this IMembershipUser user)
{
var context = HttpContext.Current.GetDataContext();
return context.ServerAccountRequests.Count(r => r.MembershipUserId == user.UserId);
}
}
}
Or, alternatively, just passing the least information I require for the query:
namespace Application.Website.Main.Business.Entities
{
public class MembershipUser
{
public static int GetRequestCount(Guid userId)
{
var context = HttpContext.Current.GetDataContext();
return context.ServerAccountRequests.Count(r => r.MembershipUserId == userId);
}
}
}
But how could I make a class so I can just use instance methods, like user.GetRequestCount()? Then the DataContract would need to be a class and not an interface... Or maybe I should have this class to also inherit from the DataContract, but then I would have to implement all of it's members, which I don't intend to do again, since that's already handled by EF at DAL level
I'm thinking I shouldn't reference the DAL project from somewhere
other than the Business project...
Depends how you reference it. The short answer is even you Business Logic (BL) shouldn't reference the DAL's physical implementation, it should reference an interface that defines the DAL; the concrete impelentation should then be loaded dynamically.
This is on the assumption that the project is beyond trivial in size - you can still write small PoC's, etc, anyway you like.
I could add "DataContract" interfaces to the Common project I already
have
I'd define the data contracts in their own assembly and not in a common project, otherwise everything that references the common "knows" about the data contracts (is that really what you want), and if you have any dependencies in the data contract then everything that references the common will get those extra unwanted dependencies as well.
Although I defining the data contracts should be it a separate assembly, the DTO/POCO objects could be in the common; I've done that before and had good results, because I use these objects to throw data between different layers - not just between the DAL and BL.
Your amin should be to keep all data access & EF references (like SQL) in the concrete DAL implementation.
Sorry if this is stupid question, because I'm a bit confused about .NET remoting and distributed object.
I want to write a webservice, and in one of its methods, I want user to pass one my object's instance as parameter. It will greatly reduces number of parameters, and help user call this method more effectively. I create some class, but when distributing them to client, only class name remains, all properties and methods are gone, just like this
public class CameraPackages
{
private readonly List<CameraPackage> _packages;
public CameraPackages()
{
_packages = new List<CameraPackage>();
}
public void AddNewCamera(CameraPackage package)
{
_packages.Add(package);
}
public void RemoveCamera(CameraPackage package)
{
if(_packages.Contains(package))
_packages.Remove(package);
else
throw new ArgumentException();
}
}
into this: (in Reference.cs)
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
public partial class CameraPackages {
}
How can I do to allow user use my object?
Thank you so much.
Web Services will only serialise public properties, so you can't do that (in that way) using web services.
You will need to manage your list of objects client side, then send the data in a transfer object (a class with just properties).
Have a look at this.
As I've stated before I'm working on a digg clone to teach myself ASP.NET MVC Inside and out but I've hit a road bump that I can't seem to avoid.
I want to be able to optimize this application as much as possible so I have my DAL which is a bunch of classes of ...Repository : Repository. Now to help optimize for performance I have my base repository classes return my ViewData objects so that they can select extra fields needed without having to create an anonymous type.
Stories have Users who have created them and Users have Votes for Stories. Pretty easy DB layout. Now I handle my own membership because the default ASP.NET membership is so bloated. In my view for the list of stories I have to determine if the current user has voted on the story being rendered. Now since I figured data access in the View shouldn't be happening it should be in either my controller or my DAL. Since I'm already returning ViewData from my DAL i added another property on the StoryViewData type named "UserVotedOn" that returns true if the user has voted on that story.
Problem with this is I have to either A) make the DAL aware of membership or B) pass in the User ID into the query methods on the DAL. Neither of these feel right to me and I'm looking for some good solutions. Any feedback is welcome.
In my MVC apps I'm using architecture that Rob Conery showed on his MVC Storefront video series and it works like charm for me.
Repository => Service + Filters => Controller => View
I've tried to simulate what you want to achieve and managed todo like this
Edit1: Changed IList to IQueryable in repository and filters
Repository
public interface IRepository
{
IQueryable<Vote> GetVotes();
IQueryable<Story> GetStories();
}
Service for getting what you want
public class Service : IService
{
private IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
if (_repository == null) throw new InvalidOperationException("Repository cannot be null");
}
public IList<Vote> GetUserVotes(int userID)
{
return _repository.GetVotes().WithUserID(userID).ToList();
}
public IList<Story> GetNotVotedStories(IList<Vote> votes)
{
return _repository.GetStories().WithoutVotes(votes).ToList();
}
}
Filters to filter your stories and user votes (These are basically extension methods). Not the nicest implementation out there, but you can rewrite later
public static class Filters
{
public static IQueryable<Vote> WithUserID(this IQueryable <Vote> qry, int userID)
{
return from c in qry
where c.UserID == userID
select c;
}
public static IQueryable<Story> WithoutVotes(this IQueryable <Story> qry, IList <Vote> votes)
{
return from c in qry
where votes.Where(x => x.StoryID == c.StoryID).ToList().Count > 0
select c;
}
}
And then you can pass current UserID in controller, not in DAL or View like you had to do before
public class HomeController : Controller
{
private readonly IRepository _repository;
private readonly IService _service;
public HomeController()
{
_repository = new Repository();
_service = new Service.Service(_repository);
}
public ActionResult Index()
{
var userVotes = _service.GetUserVotes(CurrentUserID);
var unvotedStories = _service.GetNotVotedStories(userVotes);
return View(unvotedStories);
}
}
This allows you to stay away from adding user related UserVotedOn property to your Story model
It looks like you're missing the BLL.
Actually, the right architecture of an MVC application is what many people still trying to figure out.
I personally consider UserID to be somewhat a translayer concept. It will appear on both DAL and BLL levels.
Basically, your controller method should have just a few very basic calls to the BLL, only to determine how to react to user input, whether to return on view or another.
Your view should only deal with model objects. A model should probably be filled by the business logic. You could call BL methods in a controller method in order to initialize you model object and then pass it to the view.
Controller should not communicate directly with the database. Neither should it probably deal with low level objects which comprise your domain objects and models.
P.S. i would try to avoid extensive use of ViewData. Strongly-typed model classes are a much better option. You can also group them in hierarchies to inherit some common properties. Just like your domain model classes could derive from a base class that has a UserID property defined.