Reputation: 4888
I have a dilemma about organizing my projects. I'm building an application for sending newsletters. I divided it into three projects in my solution: Newsletter.UI
(WPF), Newsletter.DAL
and Newsletter.Services
. In Newsletter.DAL
there are classes representing entities generating by EF enhanced in additional files (they are partial classes) - overriden ToString()
. In Newsletter.UI
there is of cource WPF project for presentation. The problem for me begins with Newsletter.Services
.
For now I created MailingListService.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newsletter.DAL;
namespace Newsletter.Services
{
public class MailingListService
{
private NewsletterEntities _context;
public MailingListService()
{
_context = new NewsletterEntities();
}
public List<string> GetAllMailingListsNames()
{
var query = from m in _context.MailingLists select new { m.Name };
List<string> names = new List<string>();
foreach (var m in query)
names.Add(m.Name);
return names;
}
public List<MailingList> GetAllMailingLists()
{
var query = from m in _context.MailingLists select m;
return query.ToList();
}
}
}
MessageService.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newsletter.DAL;
using System.Data.Entity;
namespace Newsletter.Services
{
public class MessageService
{
private NewsletterEntities _context;
public MessageService()
{
_context = new NewsletterEntities();
}
public List<Message> GetAllMessages()
{
return (from m in _context.Messages select m).ToList();
}
public static Message GetMessageByID(int id)
{
using (NewsletterEntities context = new NewsletterEntities())
{
Message message = (from m in context.Messages where m.MessageID == id select m).FirstOrDefault();
return message;
}
}
}
}
RecipientService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newsletter.DAL;
namespace Newsletter.Services
{
public class RecipientService
{
private NewsletterEntities _context;
public RecipientService()
{
_context = new NewsletterEntities();
}
public void addRecipient(Recipient newRecipient)
{
_context.Recipients.AddObject(newRecipient);
}
}
}
However, this gets problematic. When I open a window for creating a recipient, I create a MailingListService
instance to load mailing lists' names. Then when I try to create a new Recipient
, I create a RecipientService
instance and try to add a recipient. I get an error that I cannot use the context in different places.
How to solve this? Is my approach bad? What should it be (what should be in Services)? I don't want to get into such errors in future. I don't want to learn the MVVM approach now, I need to do this more or less the way I am doing it.
Upvotes: 1
Views: 396
Reputation: 109109
Several approaches are possible:
Use one context instance for a business transaction. The context should be created outside the services and be passed to the services through their methods or their constructors. This would require a layer of higher level services (or façades) that orchestrate the lower level services (like the ones you've got now). An IoC container could help you create and inject a context with a life cycle that is bound to that of a façade service instance.
Detach/attach. In your AddRecipient
method first detach the recipient (after checking if it is attached) and attach it to the current context. However: now the unit of work is split up between 2 context instances and you'll need a TransactionScope
to keep it transactionally sound.
Aggregate at a higher level, e.g. by creating a MailService
that deals with mailing lists, messages, and recipients.
A mixed approach. Service with their own context instance and (preferably stateless) services that have methods with a context argument in their method signatures (like public Recipient AddRecipient(NewsletterEntities context, string name, string email)
. (By passing name etc. the service is made responsible for creating new Recipient
objects or returning existing ones if they're already there).
Just a few thoughts :).
Upvotes: 1