ASP.NET MVC design - asp.net

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.

Related

Data Transfer Object, Business Object, Domain Object or something else?

In database I have table: Notes and table Comments. In my solution I have 3 projects: DAL, BLL and Web.
I need to show a user notes with comments which aren't set as spam so I have created in DAL project that class:
public class NotesWithComments
{
public Notes Note { get; set; }
public IEnumerable<Comments> Comments { get; set; }
}
I use above class in each project: DAL, BLL and Web. Is this class Data Transfer Object, Business Object, Domain Object or what?
In a repository class I have that query:
public class NotesRepository
{
DatabaseContext context;
public NotesRepository(DatabaseContext context)
{
this.context = context;
}
public IQueryable<NotesWithComments> GetNotesWithNoSpamComments()
{
IQueryable<NotesWithComments> notesWithNoSpamComments = context.Notes.Include(x => x.Comments).OrderByDescending(x => x.CreateDate)
.Select(x => new NotesWithComments
{
Note = x,
Comments = x.Comments.Where(y => y.IsSpam == false).OrderBy(y => y.CreateDate)
});
return notesWithNoSpamComments;
}
}
In BLL project I use the method from the repository class:
public class NotesService
{
private readonly IUnitOfWork _unitOfWork;
public NotesService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IEnumerable<NotesWithComments> GetNotesWithComments()
{
IQueryable<NotesWithComments> result = _unitOfWork.NotesRepository.GetNotesWithNoSpamComments();
return result;
}
}
And in Web project I use the method form the service class:
public ActionResult Index()
{
List<NotesWithComments> result = _notesService.GetNotesWithComments();
return View(result);
}
Since it neither exposes any behavior (properties or getters/setters don't qualify) nor encapsulates its structure (again, properties or getters/setters that do nothing but expose the underlying data don't qualify) it is no object at all.
No matter if the language you use calls it an object or not. It is just a data structure (which is perfectly fine if you only want to move data from one place, like a database, to another, like a UI.)
Or, to quote Dan North:
Data Transfer Object is an oxymoron
Is this class Data Transfer Object, Business Object, Domain Object or
what?
A DTO is typically a class that is mainly used for transferring data between layers or some type of boundaries..typically just an object with no behavior.
I have always referred to Domain Objects as something that maps directly to a database table. So In your example, your domain models would be Notes, and Comments.
I would consider your NotesWithComments object a dto, or possibly a view model (as you're using it as your asp.net mvc model for the view).
The practice I would normally use here is use your NotesWithComments as a dto (transfer data, no behavior, easily serializable, very clean ect), and create another class to act as your view model.
In the beginning these classes would probably be very similar, possibly the same..but if you make changes over time, or your view needs to display different things, you would just change your view model, and populate it from other dtos, or tranform your data however you need to. You could also then get rid of the properties on your view model that your view doesn't need.. (unless your view magically maps directly to every property on your current dto). It's a bit more work up front but if you're working on a big long living project I think you'd be happy you did it later on.
So you would populate your domain models using EF in your data layer, you would then use your dto and transfer that data to the Biz layer, do w/e you need there, then use your dto (could be the same one) to transfer your data to your presentation layer (mvc), and populate your view model from the dtos you receive.
Anyway that's my take on it.

ASP.NET MVC to Existing ASP.NET App with BusinessLayer.Better way to load ViewModel objects from Existing BusinessLayer?

I have a legacy asp.net web application which has 2 layers , UI and BusinessLayer. The UI project is of type ASP.NET website and BL is of type class library. The BL project has classes for entities of my app like Customer,User,Empoloyee etc.. Each class has methods for Reading from Database and Populate the object properties from the DataReader.that means the Customer Class contains my Customer object and Data Access Methods together.
Now I changed the web app to support MVC too. The old site (webforms) works as it used to be and the new upgrade to the site i am making (adding admin features to manage the site) is in ASP.NET MVC3. The routing and everything works fine. But i am worried about the structure /maintainability of the project.
For the new MVC part, I had to create ViewModels for few of the Entities like CustomerViewModel,EmployeeViewModel. I created another class called "CustomerService" With methods like GetCustomerViewModel and inside that method i call the GetCustomerMethod from the Existing BusinessLayer and read property values from the object ( of entity type mentioned in the existing BL project) and assign that to the CustomerViewModel (I will look into some AutoMapper samples for this later)object and return that from this method. My View will use this object to show data in the UI. The reason i created the "CustomerService" class is i may need to do some if condition checking or some business validations before setting the values to CustomerViewModel object. I consider that as a "Middle Layer / Service layer" so that my Controllers will be thin.
From my Customer Controller
public ActionResult Details(int id)
{
MyProject.MVCViewModel.CustomerViewModel objCustomerVM;
objCustomerVM=MyProject.MVCMiddleLayer.CustomerService.GetCustomerViewModel(id);
return View(objCustomerVM);
}
In my CustomerViewModel
public static CustomerViewModel GetCustomerViewModel(int customerId)
{
//Create an object of new ViewModel
CustomerViewModel objCustomerViewModel = new CustomerViewModel ();
//Get an object from Existing BL of Customer of type ExistingBL.Customer
ExistingBL.Customer objCustOld=new Customer(customerId);
//Check some properties of the customer object and set values to the new ViewModel object
if(objCustOld.Type=="normal")
{
objCustomerViewModel.Priority=2;
}
else if(objCustOld.Type=="abnormal")
{
objCustomerViewModel.Priority=1;
objCustomerViewModel.Message ="We love you";
}
//Some other checking like this....
return objCustomerViewModel;
}
Is this a wrong approach ? Is my code going to be messy ? I am not happy about the ViewModel since it is (almost) the duplicate code from my Existing BL entities. What is the best way to address this scenario. I am not sure about using Repository Pattern (which i saw in most of the examples) in this case ? Should i do that ?How is it going to improve my code ?
The approach that I would take would be similar to repository pattern. I would outline few key points
Since the only thing that you would be rewriting would be UI logic (View Model Object), and its fine as your UI technologies are different(asp.net vs MVC)
I would suggest you start working on interfaces so that later on you could do a dependency injection. The biggest benefit I generally with dependecy injection in mvc is while writing NUnit test cases.
public static ICustomerViewModel GetCustomerViewModel(int customerId)
{
//use DI, rather than concerete implementation
ICustomerViewModel objCustomerViewModel = new CustomerViewModel ();
//use DI, rather than concerete implementation
ExistingBL.ICustomer objCustOld=new Customer(customerId);
.
.
.
return objCustomerViewModel;
}
You could now very easily create mock objects with the help of any mocking frame work.
More or less my ViewModel classes are a redefinition of properties with only attributes, someone may argue that this is just another overhead layer, but I do this for a simple reason: I can add proper Web Validation's attributes without breaking anything (The DataLayer shoudl be shareable with other apps).
In shorts given a DataLayer class exposing a User object:
public class DalUser {
public int Id { get; set;}
public int Age { get; set;}
public string Name { get; set;}
public string Surname { get; set;}
// Business method for reading/writing/deleting
}
My viewmodel is something like:
public class VmUser : DalUser
{
[Display(Name="ID Code")]
public override int Id { get; set; }
[Display(Name="Age")]
[Required]
public override int Age { get; set; }
}
This leads me to two goals: the former is I can use Attributes without worrying about breaking something else, the latter is I can hide from user some field, prevent field injection (e.g. from FireBug - but that's includes defining an Interface and using that, not plain subclassing).
That's proves pretty usefull within my corporate (we're doomed to use EntitySpaces) and it's one of the less ugly way I've found in order to partially reuse ES generated classes.

Multiple controllers, one view, and one model ASP.NET MVC 3

I want to have one model & view that is served by multiple controllers in my ASP.NET MVC 3 app.
I'm implementing a system that interacts with the users' online calendar and I support Exchange, Google, Hotmail, Yahoo, Apple, ect... Each of these has wildly different implementations of calendar APIs, but I can abstract that away with my own model. I'm thinking that by implementing the polymorphism at the controller level I will be able to deal cleanly with the different APIs and authentication issues.
I have a nice clean model and view and I've implemented two controllers so far that prove I can read/query/write/update to both Exchange and Google: ExchangeController.cs and GoogleController.cs.
I have /Views/Calendar which contains my view code. I also have /Models/CalendarModel.cs that includes my model.
I want the test for which calendar system the user is using to happen in my ControllerFactory. I've implemented it like this:
public class CustomControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == typeof(CalendarController))
{
if(MvcApplication.IsExchange) // hack for now
return new ExchangeController();
else
return new GoogleController();
}
return base.GetControllerInstance(requestContext, controllerType);
}
}
and in my Application_Start:
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
This works. If I got to http://.../Calendar this factory code works and the correct controller is created!
This worked beautifully and I did it without really understanding what I was doing. Now i think I got it but I want to make sure I'm not missing something. I really spent time searching for something like this and didn't find anything.
One thing that concerns me is that I figured I'd be able to have an inheritance relationship between CalendarController and ExchangeController/GoogleController like this:
public class ExchangeController : CalendarController
{
But if I do that I get:
The current request for action 'Index' on controller type 'GoogleController' is ambiguous between the following action methods:
System.Web.Mvc.ViewResult Index(System.DateTime, System.DateTime) on type Controllers.GoogleController
System.Web.Mvc.ActionResult Index() on type Controllers.CalendarController
Which bums me out because I wanted to put some common functionality on the base and now I guess I'll have to use another way.
Is this the right way to do have multiple controllers for one view/model? What else am I going to have to consider?
EDIT: More details on my impl
Based on the responses below (thanks!) I think I need to show some more code to make sure you guys see what I'm trying to do. My model is really just a data model. It starts with this:
/// <summary>
/// Represents a user's calendar across a date range.
/// </summary>
public class Calendar
{
private List<Appointment> appointments = null;
/// <summary>
/// Date of the start of the calendar.
/// </summary>
public DateTime StartDate { get; set; }
/// <summary>
/// Date of the end of the calendar
/// </summary>
public DateTime EndDate { get; set; }
/// <summary>
/// List of all appointments on the calendar
/// </summary>
public List<Appointment> Appointments
{
get
{
if (appointments == null)
appointments = new List<Appointment>();
return appointments;
}
set { }
}
}
Then my controller has the following methods:
public class ExchangeController : Controller
{
//
// GET: /Exchange/
public ViewResult Index(DateTime startDate, DateTime endDate)
{
// Exchange specific gunk. The MvcApplication._service thing is a temporary hack
CalendarFolder calendar = (CalendarFolder)Folder.Bind(MvcApplication._service, WellKnownFolderName.Calendar);
Models.Calendar cal = new Models.Calendar();
cal.StartDate = startDate;
cal.EndDate = endDate;
// Copy the data from the exchange object to the model
foreach (Microsoft.Exchange.WebServices.Data.Appointment exAppt in findResults.Items)
{
Microsoft.Exchange.WebServices.Data.Appointment a = Microsoft.Exchange.WebServices.Data.Appointment.Bind(MvcApplication._service, exAppt.Id);
Models.Appointment appt = new Models.Appointment();
appt.End = a.End;
appt.Id = a.Id.ToString();
...
}
return View(cal);
}
//
// GET: /Exchange/Details/5
public ViewResult Details(string id)
{
...
Models.Appointment appt = new Models.Appointment();
...
return View(appt);
}
//
// GET: /Exchange/Edit/5
public ActionResult Edit(string id)
{
return Details(id);
}
//
// POST: /Exchange/Edit/5
[HttpPost]
public ActionResult Edit(MileLogr.Models.Appointment appointment)
{
if (ModelState.IsValid)
{
Microsoft.Exchange.WebServices.Data.Appointment a = Microsoft.Exchange.WebServices.Data.Appointment.Bind(MvcApplication._service, new ItemId(appointment.Id));
// copy stuff from the model (appointment)
// to the service (a)
a.Subject = appointment.Subject
...
a.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
return RedirectToAction("Index");
}
return View(appointment);
}
//
// GET: /Exchange/Delete/5
public ActionResult Delete(string id)
{
return Details(id);
}
//
// POST: /Exchange/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(string id)
{
Microsoft.Exchange.WebServices.Data.Appointment a = Microsoft.Exchange.WebServices.Data.Appointment.Bind(MvcApplication._service, new ItemId(id));
a.Delete(DeleteMode.MoveToDeletedItems);
return RedirectToAction("Index");
}
So it's basically the typical CRUD stuff. I've provided the sample from the ExchangeCalendar.cs version. The GoogleCalendar.cs is obviously similar in implementation.
My model (Calendar) and the related classes (e.g. Appointment) are what get passed from controller to view. I don't want my view to see details of what underlying online service is being used. I do not understand how implementing the Calendar class with an interface (or abstract base class) will give me the polymorphism I am looking for.
SOMEWHERE I have to pick which implementation to use based on the user.
I can either do this:
In my model. I don't want to do this because then my model gets all crufty with service specific code.
In the controller. E.g. start each controller method with something that redirects to the right implementation
Below the controller. E.g. as I'm suggesting above with a new controller factory.
The responses below mention "service layer". I think this is, perhaps, where I'm off the rails. If you look at the way MVC is done normally with a database, the dbContext represents the "service layer", right? So maybe what you guys are suggesting is a 4th place where I can do the indirection? For example Edit above would go something like this:
private CalendarService svc = new CalendarService( e.g. Exchange or Google );
//
// POST: /Calendar/Edit/5
[HttpPost]
public ActionResult Edit(MileLogr.Models.Appointment appointment)
{
if (ModelState.IsValid)
{
svc.Update(appointment);
return RedirectToAction("Index");
}
return View(appointment);
}
Is this the right way to do it?
Sorry this has become so long-winded, but it's the only way I know how to get enough context across...
END EDIT
I wouldn't do it this way. As Jonas points out, controllers should be very simple and are intended to coordinate various "services" which are used to respond to the request. Are the flows of requests really all that different from calendar to calendar? Or is the data calls needed to grab that data different.
One way to do this would be to factor your calendars behind a common calendar interface (or abstract base class), and then accept the calendar into the controller via a constructor parameter.
public interface ICalendar {
// All your calendar methods
}
public abstract class Calendar {
}
public class GoogleCalendar : Calendar {}
public class ExchangeCalendar : Calendar {}
Then within your CalendarController,
public class CalendarController {
public CalendarController(ICalendar calendar) {}
}
This won't work by default, unless you register a dependency resolver. One quick way to do that is to use NuGet to install a package that sets one up. For example:
Install-Package Ninject.Mvc3
I think this would be a better architecture. But suppose you disagree, let me answer your original question.
The reason you get the ambiguous exception is you have two public Index methods that are not distinguished by an attribute that indicates one should respond to GETs and one to POSTs. All public methods of a controller are action methods.
If the CalendarController isn't meant to be instantiated directly (i.e. it'll always be inherited), then I would make the Index method on that class protected virtual and then override it in the derived class.
If the CalendarController is meant to be instantiated on its own, and the other derived classes are merely "flavors" of it, then you need to make the Index method public virtual and then have each of the derived classes override the Index method. If they don't override it, they're adding another Index method (C# rules, not ours) and you need to distinguish them for MVC's sake.
I think you're on a dangerous path here. A controller should generally be as simple as possible, and only contain the "glue" between e.g. your service layer and the models/views. By moving your general calendar abstractions and vendor specific implementations out of the controllers, you get rid of the coupling between your routes and the calendar implementation.
Edit: I would implement the polymorphism in the service layer instead, and have a factory class in the service layer check your user database for the current user's vendor and instantiate the corresponding implementation of a CalendarService class. This should eliminate the need for checking the calendar vendor in the controller, keeping it simple.
What I mean by coupling to the routes is that your custom URLs is what is currently causing you problems AFAICT. By going with a single controller and moving the complexity to the service layer, you can probably just use the default routes of MVC.
As the other answers suggest, you really should refactor your code so as to not require the multiple controllers in the first place.
However, you can still have your controllers inherit from a base class controller - you simply need to make sure that when you register the routes in the Global.asax.cs, you use the overload that specifies which namespace to find the controllers and action methods for a given route
e.g.
routes.MapRoute(null, "{controller}/{action}", new[] { "Namespace.Of.Controllers.To.USe" });

ASP.NET Site, EF, Layered Architecture, is my design ok or should I correct it?

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.

Attach additional ObjectSets to ObjectContext from separate project

I hope this makes sense. I have a ASP.NET web application that uses Entity Framework. I have added a couple of custom tables to the db and created a separate project to handle the CRUD operations for those tables. I chose the separate project because I don't want future upgrades to the application to overwrite my custom features.
My problem is this. How do I attach/combine my custom ObjectContext to the ObjectContext of the application? I want to use the same UnitOfWorkScope (already in the application) to maintain the one ObjectContext instance per HTTP request. Again, I don't want to add my ObjectSets to the application's ObjectContext for my reason listed above.
Here is some code:
Widget.cs
public partial class Widget
{
public Widget()
{
}
public int WidgetId {get;set;}
public string WidgetName {get;set;}
}
WidgetObjectContext.cs
public partial class WidgetObjectContext : ObjectContext
{
private readonly Dictionary<Type, object> _entitySets;
public ObjectSet<T> EntitySet<T>()
where T : BaseEntity
{
var t = typeof(T);
object match;
if(!_entitySets.TryGetValue(t, out match))
{
match = CreateObjectSet<T>();
_entitySets.Add(t, match);
}
return (ObjectSet<T>)match;
}
public ObjectSet<Widget> Widgets
{
get
{
if((_widgets == null))
{
_widgets = CreateObjectSet<Widget>();
}
return _widget;
}
}
private ObjectSet<Widget> _widgets;
In my WidgetManager class if I was using the application's ObjectContext I would query my tables like this:
var context = ObjectContextHelper.CurrentObjectContext;
var query = from c in context.ObjectSet .... etc
What I want would be to do something like this:
var context = ObjectContextHelper.CurrentObjectContext.Attach(WidgetObjectContext);
I know this won't work but that is the gist of what I am trying to accomplish. Hope this is clear enough. Thanks.
I don't think it is possible. ObjectContext creates entity connection which connects to metadata describing mapping and database. But you have to different sets of metadata - one for ASP.NET application and one for separate project. Simply you need two connection to work with these models => you need two ObjectContexts.
FYI: The previous answer was correct at the time of the answer. It is now possible to do this using the DbContext available in EF 4.1. The caveat is that you must use the code-first strategy in order to build your custom context. In other words, you won't be able to use EDMX files to accomplish this.

Resources