I'm using Entity Framework 4.3 to generate my database from some classes. I have an Item class which has a collection of Deals that can be either free or discounted. My classes are modeled like so:
public class Item
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
//Other properties
public virtual ICollection<Deal> Deals { get; set; }
}
public abstract class Deal
{
//These properties are shared between various Deals
public int Id { get; set; }
public bool Monday { get; set; }
public bool Tuesday { get; set; }
public bool Wednesday { get; set; }
public bool Thursday { get; set; }
public bool Friday { get; set; }
public bool Saturday { get; set; }
public bool Sunday { get; set; }
public TimeSpan TimeFrom { get; set; }
public TimeSpan TimeTo { get; set; }
public int AgesFrom { get; set; }
public int AgesTo { get; set; }
public string Comments { get; set; }
public virtual ICollection<Vote> Votes { get; set; }
}
public class DiscountedDeal : Deal
{
public double PriceAfterDiscount { get; set; }
}
public class FreeDeal : Deal
{
//No properties needed here
}
Then in my onModelCreating
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<FreeDeal>().ToTable("FreeDeals");
modelBuilder.Entity<DiscountedDeal>().ToTable("DiscountedDeals");
}
I originally had a single Deal class with a boolean field to denote if it was free or not. The way I have it now seems a bit more normalized but naturally makes things more complicated.
At the front end I'm using ajax calls to send and retrieve this data but I'm not sure how treat the separate deals. If I retrieve an Item and it has 3 Deals, say 2 Free and 1 Discounted how can I deal with that? Should I have 2 Collections (1 for Free and 1 for Discounted) in my item class? Should I so go back to having one Deal class with a flag?
Without knowing the requirements, I would suggest changing the your model so that deals and and items live at the same level and you can simply apply deals to different items. As it is now you would have to create a seperate deal for every item if say you wanted to give a fifteen percent discount to items on wednesdays.
Also, I think that having a price set on the deal is a bad idea if you're letting an item have multiple deals... That forces you to have logic that determines the order of deal precedence etc. If keeping the database normailized is what you're after you I would go back to the single deal class and just give it a DealType which would be another class so that a DealTypes table is created. You could then keep the child classes and instead of having them hold the price you could give them and ApplyDeal method that would apply the deal to the item price.
Related
I'm very new to using AutoMapper and I've spent a few days googling for a solution with no luck. I am trying to map a DTO, shown below, to my entity class, which contains multiple levels of information (Year,Quarter,Season,Period,Week,Day).
Here's my DTO:
public class CalendarDto
{
public int Year { get; set; }
public int Quarter { get; set; }
public string Season { get; set; }
public int DayOfWeek { get; set; }
public string Date { get; set; }
public int WeekOfYear { get; set; }
public int DayOfYear { get; set; }
public int WeekOfPeriod { get; set; }
}
Here's the first two levels of my entity:
public class Calendar : ICalendar<string>
{
public string Id { get; set; }
public int Year { get; set; }
public string Date { get; set; }
public CalendarQuarter Quarters { get; set; }
}
public class CalendarQuarter
{
public int Year { get; set; }
public int Quarter { get; set; }
public string Date { get; set; }
public List<CalendarSeason> Seasons { get; set; }
}
As you can see, I have additional levels of nesting from year to quarter, to season, to period, to week and to day. I just provide the first level, year to quarter, because I'm sure once I figure out that one the rest will be straight forward.
I tried with the profile being set to map each class separately, as shown below, from the DTO because all property values match.
public class CalendarProfile : Profile
{
public CalendarProfile()
{
CreateMap<CalendarDto, Calendar>().ReverseMap();
CreateMap<CalendarDto, CalendarQuarter>().ReverseMap();
CreateMap<CalendarDto, CalendarSeason>().ReverseMap();
CreateMap<CalendarDto, CalendarPeriod>().ReverseMap();
CreateMap<CalendarDto, CalendarWeek>().ReverseMap();
CreateMap<CalendarDto, CalendarDay>().ReverseMap();
}
}
When I attempt to map the DTO to the entity in the handler, only the Calendar class is mapped and the CalendarQuarters list is null. It was my understanding that a profile is the same as a config and that all the mapping created in the profile would be executed when Map is executed. Obviously, I'm either wrong, have my mapping set up incorrectly, or both! Lol
var calendar = _mapper.Map<CalendarDto, Calendar>(parms.Dto);
Any suggestions would be greatly appreciated. Thanks for the assistance!
First it is important to mention that using automapper can make mapping look easier, but it is impossible to debug code and you can have problems when your project becomes big and mapping is not thing that is so complicated (you can always map explicitly and debug easily) it is just boring so it is good to have that in mind before you decide to use it, read this articles:
article1, article2.
You should read documentation if using automapper. I think that you need something like this:
CreateMap<Calendar, CalendarDto>().ForMember(dest => dest.Quarters.Quarter,
opt => opt.Quarter)
.ForMember(dest => dest.Quarters.Quarter.Seasons.Season
opt => opt.Season);
I removed reverse map because I copied this from my project and changed properties, I hope that you can apply to all properties. Of course you have many properties so you can chain ForMember and define all mappings, if you don't do this mapper is mapping only properties with same name.
I am currently working towards learning "Domain Driven Design".
I'm wondering how someone would design these entities. I simplified the object model as it would take to long to explain the "REAL" application to highlight the area of the domain I'm having trouble with.
So a CustomerInfo aggregate contains a list of Entries. It's this "Entry" object I'm having trouble designing.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<Entry> Entries { get; set; }
}
The Entry object "can" be described by a few different lists of entities. The caveat here is the "Entry" can "ONLY" be described by one of these lists. In my domain it does not make sense for an entry to have a list of Widgets AND a list of ThisThings.
To complicate things.
The entities Trinket, ThatThing, ThisThing and TheOtherThing all have the same properties, but in the context of this domain their meaning is very different.
This is my current domain model. Which I do not like as I have all this validation to make sure only one of the lists are populated by the user
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<Widget> Widget { get; set; }
public List<Trinket> Trinkets { get; set; }
public List<ThatThing> ThatThings { get; set; }
public List<ThisThing> ThisThings { get; set; }
public List<TheOtherThing> TheOtherThings { get; set; }
}
public class Widget
{
public Guid Widgetid { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket
{
public Guid Trinketid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing
{
public Guid ThatThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing
{
public Guid ThisThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing
{
public Guid TheOtherThingId { get; private set; }
public string Name { get; private set; }
public Construction Construction { get; private set; }
}
public class Construction : ValueObject<Construction>
{
public int Size { get; private set; }
public string Weight { get; private set; }
public string Unit { get; private set; }
public string Form { get; private set; }
}
What I'm struggling with is how to model this "Entry" entity properly.
1) Should I keep as designed and just rely on this crazy validation.
2) Should I be creating a polymorphic model to handle these?
public interface IWidget{
public Guid Widgetid { get; set; }
}
public interface IDifferentWidget:IWidget
{
public decimal Cost { get; set; }
public Construction Construction { get; set; }
}
public class Widget:IWidget
{
public Guid WidgetId { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
Then the Entry entity would look like, but does not prevent a ThisThing and ThatThing being added to the same Entry List.
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<IWidget> Widgets { get; set; }
}
3) Should I create different Entry entities entirely like WidgetEntry, ThisThingEntry with a common interface so the Aggregate Root would look like so:
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<IEntry> Entries { get; set; }
}
Considering the different options I've contemplated,the only solution that tackles this domain constraint "Entry" can "ONLY" be described by one of these lists is #3
Any guidance would be greatly appreciated, apologizes for the long winded question!
/*******************************REVISED DOMAIN DESIGN ***********************/
I still believe an CustomerInfo should be the aggregate because in my domain it makes sense to describe the CustomerInfo by the various entries users add to it to build a "CustomerInfo" entity.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
public Guid CustomerId { get; private set; }
private List<Entry> _entries;
public IEnumerable<Entry> Entries => _entries;
private CustomerInfo(Guid customerId /* Other properties removed, to
simplify question */){ }
public CustomerInfo Create(/* Other properties removed, to simplify
question */) {
return new CustomerInfo(Guid.NewGuid());
}
/*This is how the entity will control the state of the various lists of
entities that describe it.*/
public Entry UpdateEntry(/* Parameters removed for simplicity */) {
}
public Entry AddEntry(/* Parameters removed for simplicity */) {
}
public Entry RemoveEntry(/* Parameters removed for simplicity */) {
}
}
public class Entry {
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
private List<Widget> _widgets;
public IEnumerable<Widget> Widgets => _widgets;
private List<Trinket> _trinkets;
public IEnumerable<Trinket> Trinkets => _trinkets;
private List<ThatThing> _thatThing;
public IEnumerable<ThatThing> ThatThings => _thatThing;
private List<ThisThing> _thisThings;
public IEnumerable<ThisThing> ThisThings => _thisThings;
private List<TheOtherThing> _theOtherThing;
public IEnumerable<TheOtherThing> TheOtherThings => _theOtherThing;
private Entry(guid EntryId /*This constructor will take more parameters,
it's simplified for my question*/) { }
//Create a new instance of a Entry entity
public Entry Create(/* Parameters removed for simplicity */) {
return new Entry(Guid.NewGuid());
}
//This is how the entity will control the state of the various lists of
entities that describe it.
public Widget UpdateWidget() {
}
public Widget AddWidget() {
}
public Widget RemoveWidget() {
}
private bool CanAddAWidget() {
/* Logic to prevent a widget from being add if any of the other
lists have items*/
}
public ThisThing UpdateThisThing()
{
}
public ThisThing AddThisThing()
{
}
public ThisThing RemoveThisThing()
{
}
private bool CanAddAThisThing()
{
/* Logic to prevent a widget from being add if any of the other lists
have items*/
}
}
The problem is that you haven't designed a proper Aggregate root - a tactical Domain driven design pattern.
In your case, Entry should be an Aggregate root that ensures its own invariants. The invariant that I've identified is that Entry should not have only one kind of Thing added to its internal list. So, your code should reflect that invariant.
That being said, the Entry should have an private list of things, implemented as separate lists or just one mixed list, depending on the list/lists usage. That will prevent the client code to add items to the list without any verification. Then the Aggregate should have a addThing public method (replace that name with a more proper name from your Ubiquitous language). This method must verify the said invariant and reject any duplicates.
To use or not an abstraction depends not on DDD but on the usage of the Things. Ask yourself: does this abstraction help me to follow the OOP principles (see SOLID)? In your case is not clear because I don't know how you use those things inside the Aggregate or in the client code.
The short answer is that you can't abstract away your question like this. For example what makes a Widget and a ThisThing so simmilar that they can be listed together but a ThatThing can't be?
Just consider it like this
class Dog: IMamal {
}
class Cat: IMamal {
}
interface IMamal : IAnimal {
}
class Chicken : IAnimal {
}
Here i found that Dogs and Cats are simmilar in that if i talk about animals that i would refer to those kind of animals as mamals.
So talk to your domain expert and try to figure out what certain groups of things are called. That way you can define an interface that groups certain things together but not others
If you can't find a way why they belong together in by talking to your domain expert then it's a good bet they should be 2 separate lists.
Polimorphism should really only follow if your domain really describes it that way. If i take my animal example a Mamal might have a Walk() method and a Bird might have a Fly() method and a Hop() method (if a birt doesn't fly)
There might not be polymorphic Move() method since no biologist would describe that an animal moves, they always refer to it as either walking or flying (just for the sake of argument here, it should be the domain expert who describes entities as all having a "Name" and not the programmer who sees that "Name" "Label" and "Description" are the same kind of fields. (As Mike pointed out conincidental coheision is the thing to avoid here)
I have threeType MaliOp, LoanEBD, PrmEBD
public class MaliOp
{
public int Id { get; set; }
public int OldId { get; set; }
public byte MaliTable { get; set; }
public string Date { get; set; }
public short OpState { get; set; }
}
public class LoanEBD : MaliOp
{
public int? BId { get; set; }
public int? Loan { get; set; }
public int? PayerBimeGozar { get; set; }
[NotMapped]
public int OldId { get; set; }
}
public class PrmEBD : MaliOp
{
public int? PayerBimeGozar { get; set; }
public int? BId { get; set; }
[NotMapped]
public int OldId { get; set; }
}
the two Entity PrmEBD and LoanEBD Inherit from MaliOp. I want create DBContext in Entity Framework by by using this three types.
I have three Table in Database fro each one of them.
I don't want to use any EF Inhertance Strategy and add each one as Independent Types. but can't and EF Use either one of Inhertance strategy.
How can I do that?
create a IMaliOp Interface and let MaliOp implement it.
let the two classes implement the IMaliOp interface as well
Then use automapper (or something similar) to automatically transfer the information from the Entity object to your regular object.
This two classes would represent DTO (data transfer object). there are many strategies, out there for DTO-s
You should avoid having Classes inherit Entities, otherwise you applications classes will get too tightly coupled, and changes might prove them self to become too painful
In your context, override OnModelCreating;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PrmEBD>().ToTable("PrmEBDs");
modelBuilder.Entity<LoanEBD>().ToTable("LoanEBD");
modelBuilder.Entity<MaliOp>().ToTable("MaliOp");
}
This will create three separate tables in your database.
You will need to make sure that when you do a query over MaliOp, that you don't pull in instances from all three tables. You may want to go wit the approach of creating a common interface for all three, so that they don't actually inherit from each other, too
Hi I have a situation in witch I have to create some custom validation attributes because the way my model is created.The model looks something like this:
public class EvaluationFormDataContract
{
public int StudentAssignmentInstanceId { get; set; }
public int EvaluationType { get; set; }
public List<CategoriesOnEvaluationDataContract> Categories { get; set; }
}
public class CategoriesOnEvaluationDataContract
{
public string Memo { get; set; }
public int CategoryId { get; set; }
public List<QuestionsOnEvalCategoryDataContract> Questions { get; set; }
// Fields needed for validation
public bool? HasMemo { get; set; }
public bool MemoIsMandatory { get; set; }
}
public class QuestionsOnEvalCategoryDataContract
{
public string Memo { get; set; }
public string Grade { get; set; }
public int QuestionId { get; set; }
// Fields needed for validation
public bool HasGrade { get; set; }
public bool HasMemo { get; set; }
public bool ShowOnlyMemo { get; set; }
}
As it can be seem the model is composed two levels deep.
And I will have to validate starting from the second level , where I will check if the model HasMemo and if MemoIsMandatory.
The third validation should be done at the 3rd level where I have to check if it HasGrade and HasMemo.
Normaly if it were up to me I would split this in three separate calls to the server but we are depending on an legacy project and for the moment I have to make this work.
The post action will be called via an ajax call and will have all this data into it.
Now my question is where should I add the validation attribute?
Should it be added at the top on Categories , making it directly responsible for all the levels of the model?
Or I should place it on each model and find a way to make the data binder aware of it? If so how can I do this?
You can do both. If you implement System.ComponentModel.DataAnnotations.IValidatableObject interface at the top-most level, you can do whatever you want with the properties in the entire graph and return the errors.
public class EvaluationFormDataContract : IValidatableObject
{
// All properties go here
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext)
{
if (// do what you want)
yield return new ValidationResult("message");
}
}
Or, you can apply attributes at the lower levels and automatically binding takes care of validating the properties in the graph. You don't need to do anything special.
I've read several articles about bunch of EF and DTO, and I need some clarification about using EF Code First and DTO in n-tier scenario with WCF.
Let's look a these classes:
public class Order
{
public int Id { get; set; }
public DateTime ShipDate { get; set; }
public ObservableCollection<OrderDetail> Details { get; private set; }
}
public class OrderDetail
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal Quantity { get; set; }
}
When user want to edit existing order, my client application (WPF MVVM app) requests some DTO, which then being converted to Order instance. Then, user makes some changes in order through UI - e.g., changes ShipDate, removes two positions, modifies one, and adds one.
Now I want to deliver changes to the server. As far as I understand DTO concept, I need to construct some DTO type, containing info about changes has been made:
[DataContract]
public class UpdateOrderDTO
{
[DataMember]
public DateTime ShipDate { get; set; }
[DataMember]
public Collection<OrderDetail> NewDetails { get; private set; }
[DataMember]
public Collection<OrderDetail> ModifiedDetails { get; private set; }
[DataMember]
public Collection<OrderDetail> DeletedDetails { get; private set; }
}
But when, and where should I to create this DTO? I mean, I can't create it on submitting changes - there's no change tracking information in Order class.
Looks like, this object have to be created together with Order after it was requested for edition by user. This allows to track changes... Am I wrong?
Please note, that the question isn't about STEs. For some reasons, I don't want/can't use them in current project.
Thanks a lot for sharing your experience.