What are some best practices for handling validation of domain entities that depends on other domain entities using POCOs that one creates when implementing an ORM based off of the EF Code First?
Here's the situation I am trying to work through: I have a class that represents a client computer, and there is a property of that class that represents the computer's IP. I need that to be unique, but I cannot find an elegant solution for enforcing that constraint. Currently I do it in the service layer where I update/insert the entity.
-- UPDATE --
I know that EF doesn't support unique constraints and I have already added the constraint to the database table, but I'd rather catch the constraint before I hit the database. What I was looking for was a better way to handle validation that is dependent on other entities in general and was using the unique constraint as an example.
-- UPDATE 3/28/2010 --
For reference, here is how I currently handle the unique constraint for IP (_unitOfWork is of type SqlMessageUnitOfWork: basically it wraps around the DBContext I am using, exposing IDbSets for all relevant tables):
public class ClientService : IClientService
{
public ValidationResult InsertClient(ClientDTO clientDTO)
{
var existingClient = _unitOfWork.Clients.Where(x => x.IP == clientDTO.IP).SingleOrDefault();
if (existingClient != null)
{
return new ValidationResult("IP already in Use.", new[] { "IP" });
}
else
{
var newclient = new Client();
ClientEntityMapper.MapToEntity(clientDTO, newclient, _unitOfWork.Terminals);
_unitOfWork.Clients.Add(newclient);
_unitOfWork.Commit();
}
return ValidationResult.Success;
}
...
private IUnitOfWork _unitOfWork;
public ClientService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
public interface IUnitOfWork
{
IDbSet<Message> Messages { get; }
IDbSet<Terminal> Terminals { get; }
IDbSet<Client> Clients { get; }
IDbSet<MessageDisplayInstance> MessageDisplayInstances { get; }
void Commit();
}
public class SqlMessageUnitOfWork : IUnitOfWork
{
readonly VisualPagingDbContext _context;
public SqlMessageUnitOfWork()
{
_context = new VisualPagingDbContext();
}
public void Commit()
{
_context.SaveChanges();
}
public IDbSet<Message> Messages
{
get { return _context.Messages; }
}
public IDbSet<Terminal> Terminals
{
get { return _context.Terminals; }
}
public IDbSet<Client> Clients
{
get { return _context.Clients; }
}
public IDbSet<MessageDisplayInstance> MessageDisplayInstances
{
get { return _context.MessageDisplayInstances; }
}
}