Altering Domain Entities When Changing Persistence Layer - c#

In my app, I've been using a DB that stored its IDs as strings. The DB also stored another property (Etag) for each document/row. Because of that, I've had my domain entities derive from this base class:
public class EntityBase : NotifyPropertyChangedBase
{
public string Id { get; set; }
public Guid ETag { get; set; }
}
Now I'm adding another data layer to my application, and I don't want to remove the old one. It would be nice to be able to switch and use a particular data layer based on a run-time decision. The issue is that I want to store Id as an int in the new DB. And ETag is an unnecessary concept in that new DB.
I'm struggling with how to manage this change. If I change EntityBase.Id to an int, then the old data layer won't compile. I'd like to use a certain EntityBase if using the old data layer, and a different EntityBase if I'm using the new data layer. That's just one thought. Maybe there's a better approach? Any suggestions on how I can make this work?
By the way, I believe that persistence layer issues shouldn't work there way up into domain layer objects (like Id being a string or int). However, it's too late, and this is the situation in which I find myself. I'm hoping someone has some good advice on how to proceed.
I was thinking about adding an Id2 to EntityBase:
public class EntityBase : NotifyPropertyChangedBase
{
public string Id { get; set; }
public int Id2 { get; set; } // New property for new DB only
public Guid ETag { get; set; }
}
Then, in my new DAL mapping, I would map the Id column in the table to Id2 instead of Id. But that's not going to work because my business logic references Id only. Still thinking... I may be stuck...
As a hack, I could leave EntityBase in its original form. Then, in the new DAL, when I perform the ORM, I could just convert the ID of the table to a string.

I suggest to add one more layer then.
For instance, to create a new class like this:
public abstract class CommonEntityBase<T> : NotifyPropertyChangedBase{
public T Id {get;set;}
}
And then, derive your old EntityBase from this class:
public class EntityBase : CommonEntityBase<string>{
//this property is present only in this old implementation
public Guid ETag { get; set; }
}
So now, you can create a new layer and use a base class for that as well:
public class FancyEntityBase : CommonEntityBase<int>{
//No ETag concept here - ad new properties, methods, etc.
}
However, there is a question if you really need to change your primary keys to be integers.
This may result in performance issues when the ORM is used.

Related

Having two classes representing the same table in Entity Framework?

I am trying to clean up some Entity Framework data contexts that were originally created without any naming conventions. I would like to keep the old classes but also have the new, properly named class available at the same time so that all the other projects that use these data contexts don't need to be changed right away. I will be marking the old class as Obsolete using data annotations so that they won't be used on any new development. Only the classes will be changed, the database is going to be stuck with the poor naming for eternity.
When I create a new class based on a table that cleans up all the naming while still keeping the old class representing the table I can create the classes but when I try to use either one I get he following error:
The entity types 'Client' and 'lu_Clients' cannot share table 'lu_Clients' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.
My ugly class:
[Obsolete("Use Client class instead")]
public class lu_Clients
{
[Key]
[Column("ClientsSeq")]
public int ClientsSeq { get; set; }
[Column("ClientsID")]
public string ClientsID { get; set; }
[Column("ClientsName")]
public string ClientsName { get; set; }
}
My cleaned up class:
[Table("lu_Clients")]
public class Client
{
[Key]
[Column("ClientsSeq")]
public int Sequence { get; set; }
[Column("ClientsID")]
public string Id { get; set; }
[Column("ClientsName")]
public string Name { get; set; }
}
Any suggestions on how to get the two classes to the same table concept to work? Or is there a better way to maintain compatibility with the obsolete and the new going forward?
Why do you need to keep both? I would rename each field in the old class to match the new class (use VS rename feature to make sure all valid fields are renamed), then rename the old class name to new class name (which will generate conflicts), but then delete the old class. Now all code is using the new class and the old class doesn't exist.
Could you make the new Class inherit from the table and then change lu_clients to inherit directly from clients class instead, effectively mapping via the new class until the old ugly class is no longer needed?

Do I need to use POCO Classes with Entity Framework 6

The following class was Auto generated from a template using the Entity Framework Model.
namespace Entities
{
using System;
using System.Collections.Generic;
public partial class Country
{
public Country()
{
this.Regions = new HashSet<Region>();
}
public long CountryId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool Preferred { get; set; }
public System.DateTime LastChanged { get; set; }
public virtual ICollection<Region> Regions { get; set; }
}
}
I have a Wcf web service that returns POX (Xml) and Json only. I am wanting to return my own serialised object like;
public class MyResponseObject
{
public int RequestId {get;set;}
public List<Country> CountryList {get;set;}
//other properties
}
But I don't want to return the Regions ICollection.
The object can then be returned using something like
Newtonsoft.Json.JsonConvert.SerializeObject()
Am I best returning my own serialised POCO object in this manner ?
In projects like these, your classes can be split into two types:
Database entity objects (what Entity Framework works with)
Data contract objects (what WCF or your web-service works with)
While it is possible to use the same objects for both, it is not recommended because the database entity objects are an internal implementation concern that is separate from the external interface (your webservice). You might add or remove columns to your database table and not want your API contracts to change. But usually you'll want to hide information from service-consumers, like a database table Users ( UserId, Password ), you definitely don't want the Password property going out!
Another reason not to is that you later might want to add attributes to your webservice contract classes (e.g. to control output formatting or input validation), adding these to entity objects is painful, if not impossible in some cases.
I know it sounds like a needless duplication of work as the majority of classes will have identical members, but it makes sense from a long-term perspective.
Fortunately tools like AutoMapper can speed-up the process of copying data from your database entity objects to your data contract objects.

Updating related entities DDD

I'm confused on how I'm going to updated related entities using DDD. Let say I have a Employee Class and Workschedule Class. How should I updated a specific workschedule of a certain employee? The relationship between Employee and Workschedule is One-To-Many. Below is the code I'm using how to Add/Update a certain workschedule.
public class Employee
{
public int EmployeeId { get; set; }
public virtual ICollection<WorkSchedule> WorkSchedules { get; set; }
public WorkSchedule AddWorkSchedule(WorkSchedule workSchedule)
{
this.WorkSchedules.Add(workSchedule);
return workSchedule;
}
public WorkSchedule EditWorkSchedule(WorkSchedule workSchedule)
{
var originalWorkSchedule = this.WorkSchedules.FirstOrDefault(w => w.WorkscheduleId == workSchedule.WorkscheduleId);
originalWorkSchedule.ClockIn = workSchedule.ClockIn;
originalWorkSchedule.ClockOut = workSchedule.ClockOut;
return originalWorkSchedule;
}
}
public class WorkSchedule
{
public int WorkScheduleId { get; set; }
public DateTime ClockIn { get; set; }
public DateTime ClockOut { get; set; }
public int EmployeeId { get; set; }
}
Is this correct? Did I follow DDD correctly? Also, my thinking right now Workschedule is a value object but I'm putting and ID for normalization purposes
your Model should be "POCO" class
CRUD methods such.. Add or Edit will be considored as part of "Service" or "Repository"
here is a quick idea that just came to my mind / how should it look like and its usage..
IRepository repository { get; set; } //implement Interface and inject via IoC Container
//..usage
var employee = repository.GetEmployee(123); //get by id
//..new WorkSchedule
employee.WorkSchedules.Add(workSchedule);
var result = repository.Save(employee);
Since everything here is EF related, it isn't much of DDD. IF the code works as desired, then it's ok. But DDD has no relationship to EF or any other ORM. You should design the Domain objects, without caring at all about the database or an ORM. Then, in the repository you map the Domain entities to Persistence entities which will be handled by the ORM.
Also, my thinking right now Workschedule is a value object but I'm putting and ID for normalization purposes
This is the consequence when the layers and models are mixed. You don't need an ID in the domain but you need an id for persistence. Trying to fit both requirements in one model and calling that model Domain leads to nowhere.
EF it is not for DDD, it is too clumsy. EF is for same codemonkeys who likes t map SQL tables to Entities and do it like ActiveRecord antipatter, but after more intelligent developers started to call this as a bad practice, they started to use ORM, entities and continue monkeycoding.
I'm struggling with EF last 3 years to let it work DDD way. It successfully resists and wins. Without hacks it doesn't work.
The on-to-many relations still doesn't work as expected, there is not way to create entities with constructor, not the public properties and so on.

Entity Framework 4.1 Loose Coupling on Entities

Need a little help please if anyone can shed some light on this.
I've created a code-first MVC 3 application which I have working fine. I'm refactoring now to remove as much coupling as possible as I want the domain model to be used in various other MVC 3 applications later on. What I have now is a collection of entities which are persisted via a normalised database and they are CRUD-ed through a repository pattern. I have used Ninject to DI the repositories via the controller's constructor and am using models within the MVC 3 project to act as DAOs.
So, within the domain I have an entity called Case that has a foreign key to another case Client that looks like this:
public class Case : ICase
{
[Key]
public int CaseId { get; set; }
public string CaseName { get; set; }
public DateTime DateCreated { get; set; }
public IClient Client { get; set; }
}
Then I have an interface (the interface exists mainly to implement it to the view model to add my data annotations - I know I could add the annotations to the domain object but as I said I want to use this domain model in other applications which will have a different ubiquitious language.
public interface ICase
{
int CaseId { get; set; }
string CaseName { get; set; }
DateTime DateCreated { get; set; }
IClient Client { get; set; }
}
And then I have my view model within the MVC 3 project.
public class CaseModel : ICase
{
[HiddenInput(DisplayValue = false)]
int CaseId { get; set; }
[Required(AllowEmptyStrings = false)]
[MaxLength(100)]
string CaseName { get; set; }
[RegularExpression("")]
DateTime DateCreated { get; set; }
IClient Client { get; set; }
}
So, my first problem is this: changing my foreign key reference for Client to IClient is a new thing, and it returns a null object. When the type was a concrete class it returned fine - I assume this is because EF4.1 tries to create an instance of IClient. Am I totally wrong here or is there a way around this?
My second problem (which may negate my first problem) is am I also doing something wrong by adding data annotations to a view model inheriting the interface of my domain entity? Should I be using model meta data? If so, how do I use meta data in such a way that I can make the data annotations unique to each project without touching the domain?
Thanks!
Caveat: I'm not an expert on EF or MVC3.
We're in the process of building EF Code First entities, and we're not planning on adding interfaces to the entities. Repositories get interfaces. Units of Work get interfaces. Entities don't. Repositories return concrete entities, which are POCOs. Entities may be coupled to related entities. Models and other classes will typically get repository interfaces and/or unit of work interfaces injected in. For testing, we'll just new up some POCO entities and return them from the mock repositories.
We're planning to make the relevant POCO properties virtual so that EF can create proxies.
If you want to decouple a view from concrete entities, I'd first ask what value you expect to gain from that. Is the view going to be reused with different entities? If so, one option would be to use something like AutoMapper to copy the properties over. You'd have to be aware of the immediate access of lazy-load properties, though.

ASP.NET MVC: Where should this business logic go?

I'm working on my first real MVC application and I'm trying to follow general OOP best practices. I'm refactoring some simple business logic that I had in a controller into my domain model. I've been doing some reading lately and it seems pretty clear that I should put the logic somewhere in a domain model entity class in order to avoid the "anemic domain model" anti-pattern.
The application will allow people to purchase leases for parking spaces. Rates are determined by the length of the spot and whether or not the customer is a member of the business park.
So I have entity classes in my domain model that look like this (simplified):
public class Customer
{
int ID { get; set; }
string Name { get; set; }
bool IsMember { get; set; }
}
public class ParkingSpace
{
int ID { get; set; }
int Length { get; set; }
}
public class ParkingSpaceLease
{
int ID { get; set; }
DateTime OpenDate { get; set; }
DateTime CloseDate { get; set; }
Customer Customer { get; set; }
ParkingSpace ParkingSpace { get; set; }
}
Edit: Just to clarify the LeaseQuote is not an entity class as it is just used to display the cost breakdown to perspective customers and is not persisted anywhere.
public class LeaseQuote
{
int SubTotal { get; set; }
int Discount { get; set; }
int Total { get; set; }
}
Now as a feature of the application I need to be able to generate quotes for different customer and parking space combinations. The quotes will normally be accessed outside the context of actually creating a lease such as when a customer calls up to inquire about a price.
So what is the best way to go about this? Does it make sense to instantiate a new ParkingSpaceLease object inside the controller just to call a GetQuote method on it?
var lease = new ParkingSpaceLease();
var quote = lease.GetQuote(length: 168, isMember: true);
return Json(quote);
Or should the LeaseQuote class have the method?
var leaseQuote = new LeaseQuote();
var quote = leaseQuote.GetQuote(length: 168, isMember: true);
return Json(quote);
It feels strange putting the logic in the actual ParkingSpaceLease class. I guess it feels kind of "heavy" to create a new lease object when I know that I'm not going to actually do anything with it other than access the GetQuote method which seems kind of like a separate service.
So where should the GetQuote method go and why should it go there?
It almost sounds like your LeaseQuote isn't an entity and more of a business level class. I mean, you're not storing it in the database anywhere, are you? And it's not a part of another data object.
When I see this
Now as a feature of the application I need to be able to generate quotes for different customer and parking space combinations. The quotes will normally be accessed outside the context of actually creating a lease such as when a customer calls up to inquire about a price.
I think of a method signature like this
public LeaseQuote GetQuote(Customer customer, ParkingSpace parkingSpace, int length)
But with that in mind, I'd probably also want to store information about the cost of the parking space within the ParkingSpace entity and (if applicable) the customer's discount in the Customer entity.
Where would this stuff go? In a model class (business model, not LINQ or Entity model) that accesses your entities and serves as a provider for your controller.
Now I know that's not using your models exactly as written. And it could just be personal bias. But when I think about data models and data entities, they should not have any addon methods outside of what's coming back from the database. They should just represent the data unaltered as it appears in the database. If you're acting on the data, that belongs in a tier above the data entities.
Update:
What I am curious about from your example is why one would want to pass the full Entity objects (Customer and Parking Space) versus just the properties needed to perform the calculation?
It depends on your standard of code. Exposing the entity itself could be dangerous if the consuming code manipulates the entity. I prefer passing the entity mainly because that's what I'm used to. But I'm also careful not to manipulate the entity on the way in. That, and I think the method signature reflects what the GetQuote method is focused on; it's related to a customer and a parking space.
I could also make the case that if more fields go into the Entity later that can effect the GetQuote method, then the method signature doesn't have to change. In this case, only the implementation for GetQuote has to change.
Short answer: Preference.
Just make GetQuote a static method in ParkingSpaceLease.
I think you may have your object model slightly askew, which would lead to your concern about the lease being the wrong place from which to get a quote. It seems to me that a lease would be wholly composed by the parking space which is being leased, and would be related only to the customer purchasing the lease. IOW:
public class ParkingSpace
{
int ID { get; set; }
int Length { get; set; }
IEnumerable<ParkingSpaceLease> Leases { get; set; }
LeaseQuote GetQuote(Customer customer/*, other relevant parameters */) { ... }
}
public class ParkingSpaceLease
{
int ID { get; set; }
DateTime OpenDate { get; set; }
DateTime CloseDate { get; set; }
Customer Customer { get; set; }
}
public class LeaseQuote
{
//Properties
ParkingSpaceLease GetLease();
}
EDIT I missed the part about the LeaseQuote being a separate class.

Categories

Resources