I've got a situation where I have data classes that are generated by a database with various properties on them e.g which I cannot modify.
public DataClass
{
public string PropertyX {get; set;}
public int PropertyY {get; set;}
public float PropertyZ {get; set;}
}
Some of these classes may have 20 or so properties. When updating the data a "transient" copy of the "persistent" data is made, then the properties updated on the transient and copied from the transient to persistent.
Which is fine although if only changing one property isn't very efficient.
I wanted to find out if there is a way in c# that I could create a list of flagged properties or add attributes onto certain flagged properties I wish to update.
So the end result would be (please note this is all pseudo)
DataClass transientObj = new DataClass(Transient);
[FlagPropertyToUpdate] //This is the bit I have no idea how to do
transientObj.propertyX = "updateOnlyMe!";
DataClass persistantObj = new DataClass(Persistant);
UpdateData dataUpdater = new UpdateData(transientObj,persistantObj)
dataUpdater.save();
public UpdateData
{
public void save(){
//some how know to only update propertyX and not all three properties
}
public UpdateData(DataClass trans, DataClass pers)
}
Any assistance on how I could go about doing this (and if its possible) would be highly appreciated!
I'd recommend creating a DTO (Data Transfer Object) that supports dirty-flagging the relevant properties. That way your classes can remain unchanged. Have a look at Automapper.
Then again, I'd invite you to reconsider your assertion that updating the complete set of properties is inefficient, assuming they're simple types. Writing to an entire row in a database is generally no more expensive than writing a single column. I'd be more concerned wth concurrency in the situation you describe.
I think View Model's will fit here.
The ViewModel is an abstraction of the View or a conceptual state of the data as opposed to the real state of the data in the Model.
So in this case you will have a class like:
public DataClassViewModel
{
//Define all relevant properties here.
...
public DataClassViewModel(DataClass model) //Constructor
{
//Initialize the view model from the model.
}
public DataClass GetModel()
{
//Depending on changes in the view model, model could be updated here.
}
public void UpdateData()
{
}
}
You can read more about view model's here:
Model-View-ViewModel (MVVM) Explained
How we do MVC – View models
What is ViewModel in MVC?
Although the articles point to MVC/MVVM UI architectures, view model is quite a general concept.
Related
I have a model that has some related data in navigation properties, like so:
public class Document
{
[Key]
public int DocumentId { get; set; }
public string DocumentName { get; set; }
public virtual ICollection<DocumentBeneficiary> DocumentBeneficiaries { get; set; }
public virtual ICollection<DocumentExecutor> DocumentExecutors { get; set; }
public virtual ICollection<DocumentSuccessor> DocumentSuccessors { get; set; }
}
I understand how to do eager loading of this related data from a controller method, like so:
var doc = context.Documents.Include(x => x.DocumentBeneficiaries)
However, what I want to do is write a member method inside the model that takes the data related to an entity, does some processing, and outputs a string. Something like this:
public class Document
{
...
public string ProcessStuff() {
//use data in navigation properties here like so:
foreach (var d in DocumentBeneficiaries) { ... }
}
}
Is this allowable? I can't seem to find anything about it on google. Will it load the related data lazy vs. eager depending on how I load the entity in the controller prior to calling the method in the model?
I realize that some schools of thought hold that models should have no methods, but others say it's ok to put business logic in the model. If I have to I suppose I can make this a controller method, but this way makes more sense to my design if possible. Sorry if this is a somewhat speculative question, but I can't seem to find any info on this pattern.
Yes it will load the DocumentBeneficiaries when you invoke ProcessStuff method as long as Lazyloading is enabled, thou it may not be a good design (my opinion) to add business logic directly into the model, but as you stated, there are some who like it and some who don't.
If you don't load the child collection ahead of time using Include and Lazyloading is enabled, then you will end up making extra database trips while executing ProcessStuff(). Using Include pre loads the data you need with less number of database round trips. It is always better to make less database trips whenever possible.
If Lazyloading is disabled, you have to use Include before invoking ProcessStuff()
I've just read quite a few posts on Table per Type/TPT and the discriminator column, but, I'm not really any the wiser in my situation.
Taking an example: I have a MVC app that has a model called Foo. This has one property called Bar that is stored as a one to many elsewhere.
I am the only one using this app and I didn't want to spend a lot of time on it, so I just wanted the quickest way to add items to the list in Bar. Because of this, I made a new class called FooViewModel that is derived from Foo, and had a string property called BarTemp.
The basic idea is that I can type 111, 222 , 333,444 in to a standard text field and have the edit/create controllers clear whitespace and split to a list on the comma.
What I can't figure out is that the view model will never be written to EF, so, why is it creating the discriminator column.
It looked like when I tried to scaffold a migration, it event tried adding BarTemp to the DB.
I have since created a new type called the same, but instead of deriving, I just have Foo and BarTemp as properties in it which works as expected, but, I still don't get what happened and would like to learn more.
It's because EntityFramework parses the hierarchy. Just because your current code doesn't ever save a BarTemp, there's nothing explicitly stopping you from writing:
context.Bars.Add(new BarTemp());
There's nothing EntityFramework can do to detect the above. So, it plays safe and assumes that if you inherit from an entity, your subclass will also be an entity. That's a correct assumption - and you shouldn't make view models inherit from the entity. Neither should they be properties. I'm really unsure how you've setup your current code, but the classes should be completely distinct. For example, it should look something like:
class BarTemp
{
public string BarId { get; set; }
public string Foos { get; set; }
}
class Bar
{
public string BarId { get; set; }
public ICollection<Foo> Foos { get; set; }
}
class Foo
{
public string Id { get; set; }
public Bar Bar { get; set;
}
Your view model should know nothing about the entities, and the entities should know nothing about the view models. Your code accepting the input should do the work converting the view model to the entity. For example:
private void Update(BarTemp barTemp)
{
var bar = context.Bars.GetById(barTemp.BarId);
foreach (var foo in barTemp.Foos.Split(","))
{
var foo = context.Foos.GetById(foo);
bar.Foos.Add(foo);
}
context.Save();
}
Don't take the above as an example of good code - it's extremely inefficient - but it should show you an example of where the conversions should take place, and how to keep the entities and view models separate.
I am using Entity Framework code first in a test project. I have distributed code in different layers as below
Model Layer
This layer is reference in all other layers/projects
namespace Model
{
Public class Sample
{
Public string Name
[ForeignKey("Category")]
public int CatrgoryId
Public Category Category
}
}
DAL
namespace DAL
{
public class SampleContext:DbContext
{
...
}
}
In DAL I only have the context class and migrations
BLL
namespace BLL
{
public class SampleBLL
{
public List<Sample> GetAll()
{
retrn new SampleContext().Samples().ToList()
}
}
}
UI
namespace UI
{
public class UIHelper
{
public List<Sample> GetSamples()
{
return new SampleBLL().GetAll();
}
}
}
It does not seem practical to use EF entity model objects in UI as they might have navigation properties and cannot be directly bound to controls like DataGridView because in that case the datagridview will have both the CategoryId and Category columns while I need to display the Category Name as Category eg DataGridView.DataSource = new SampleBLL().GetAll()
One solution that I could think of is to use ViewModel classes and manually map the entity model objects to viewmodel objects in BLL and return viewmodel objects to UI, But, introducing a new layer ViewModel would mean replicating all my Model objects with minor changes.
Forexmple the view model for above sample model would
namespace Model
{
Public class Sample
{
Public string Name
public int CatrgoryId
public string CategoryName
}
}
Is the viewmodel layer only option I have or there is an other efficient way to consume the Entity Models directly in UI.
It is a very bad idea to use Entity Models directly in UI, mainly because of the issues you've exposed. More importantly, you're currently only retrieving data and displaying it "as is", but the slightest change in UI affects DB, and vice-versa. Any more complexe logic would be very troublesome to implement, AFAIK
At work, we use a Transport namespace to store classes corresponding to our entities and assemblers methods to convert entities to transport classes once we're done with retrieval logic. This way we're separating model from controller, and can safely manipulate data without any risk of unwantingly affecting the database.
I have a good understanding of EF, and generated my database successfully. Now, I am struggling with adding dynamic properties to one of the entity classes. For example, I have a Post class, and other users can make comments to the posts. When I list the existing posts, I want to display the number of comments made to corresponding post.
One solution might be having a property called CommentCount, and updating the Post by increasing the (int) value of the CommentCount property by 1 when a new comment is made.
The other solution, and I think it is a better solution, is that when retrieving the post from the DB, the number of comments associated with the post can be computed and retrieved at the same time and assigned to CommentCount property of the post instance. However, I do not know how to achieve this with EF.
Which approach is highly recommended? Or, is there any other ways of doing this? If it is the second one, how can I achieve this with EF?
1) You should simply consider not putting the property called CommentCount into your model. When you develop for example a WPF Windows application, you should consider using MVVM pattern and the CommentCount would belong to your ViewModel class and not to your Model class. There you implement INotifyPropertyChanged and you can use it from your frontend Views. Analogically there is MVC pattern for ASP.NET etc.
There are other design patterns like Repository pattern. Using this pattern you can create the CommentCount in your repository class and not in your
model class. This would be similar to your second solution.
2) I assume from your question that you are using code-first approach:
generated my database successfully
If you do so and you wish to include CommentCount directly in your Model class, you can do it this by adding partial class file to your project like this:
namespace DBModel.Models
{
public partial class Post
{
public int CommentsCount
{
get { return this.Comments.Count; }
}
...
But I cannot see why to create extra property in your model just for that.
On the other hand adding this field as a computed field into your SQL database could make sense and then it would be part of your EF model.
If you calculation is very complex you should try creating a View in your DB and then add it to your Model?
But if your Model have something simple like
class Post {
public int postid { get; set; }
public virtual ICollection<comment> comment { get; set; }
}
In your controller you can do
db.post(x => x.postid == yourid).comments.count()
to get total of comment
or in your view
#foreach (var item in Model)
{
<li>item.postid;</li>
<li>item.comment.Count();</li>
}
Or update your class
class Post {
public int postid { get; set; }
public virtual ICollection<comment> comment { get; set; }
public int CommentCount
{
get
{
return comment.Count();
}
}
}
Just remember bring related data in your query.
In my case POI have properties parish_id, sector_id, city_id and parish have municipality, and municipality have state.
Using this query I can get Poi with all the related data.
filter = db.poi
.Include("parish")
.Include("sector")
.Include("city")
.Include("parish.municipality")
.Include("parish.municipality.state")
.Where(x => x.sector_id == SectorID);
After watching NDC12 presentation "Crafting Wicked Domain Models" from Jimmy Bogard (http://ndcoslo.oktaset.com/Agenda), I was wandering how to persist that kind of domain model.
This is sample class from presentation:
public class Member
{
List<Offer> _offers;
public Member(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
_offers = new List<Offer>();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Offer> AssignedOffers {
get { return _offers; }
}
public int NumberOfOffers { get; private set; }
public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc)
{
var value = valueCalc.CalculateValue(this, offerType);
var expiration = offerType.CalculateExpiration();
var offer = new Offer(this, offerType, expiration, value);
_offers.Add(offer);
NumberOfOffers++;
return offer;
}
}
so there are some rules contained in this domain model:
- Member must have first and last name
- Number of offers can't be changed outside
- Member is responsible for creating new offer, calculating its value and assignment
If if try to map this to some ORM like Entity Framework or NHibernate, it will not work.
So, what's best approach for mapping this kind of model to database with ORM?
For example, how do I load AssignedOffers from DB if there's no setter?
Only thing that does make sense for me is using command/query architecture: queries are always done with DTO as result, not domain entities, and commands are done on domain models. Also, event sourcing is perfect fit for behaviours on domain model. But this kind of CQS architecture isn't maybe suitable for every project, specially brownfield. Or not?
I'm aware of similar questions here, but couldn't find concrete example and solution.
This is actually a very good question and something I have contemplated. It is potentially difficult to create proper domain objects that are fully encapsulated (i.e. no property setters) and use an ORM to build the domain objects directly.
In my experience there are 3 ways of solving this issue:
As already mention by Luka, NHibernate supports mapping to private fields, rather than property setters.
If using EF (which I don't think supports the above) you could use the memento pattern to restore state to your domain objects. e.g. you use entity framework to populate 'memento' objects which your domain entities accept to set their private fields.
As you have pointed out, using CQRS with event sourcing eliminates this problem. This is my preferred method of crafting perfectly encapsulated domain objects, that also have all the added benefits of event sourcing.
Old thread. But there's a more recent post (late 2014) by Vaughn Vernon that addresses just this scenario, with particular reference to Entity Framework. Given that I somehow struggled to find such information, maybe it can be helpful to post it here as well.
Basically the post advocates for the Product domain (aggregate) object to wrap the ProductState EF POCO data object for what concerns the "data bag" side of things. Of course the domain object would still add all its rich domain behaviour through domain-specific methods/accessors, but it would resort to inner data object when it has to get/set its properties.
Copying snippet straight from post:
public class Product
{
public Product(
TenantId tenantId,
ProductId productId,
ProductOwnerId productOwnerId,
string name,
string description)
{
State = new ProductState();
State.ProductKey = tenantId.Id + ":" + productId.Id;
State.ProductOwnerId = productOwnerId;
State.Name = name;
State.Description = description;
State.BacklogItems = new List<ProductBacklogItem>();
}
internal Product(ProductState state)
{
State = state;
}
//...
private readonly ProductState State;
}
public class ProductState
{
[Key]
public string ProductKey { get; set; }
public ProductOwnerId ProductOwnerId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<ProductBacklogItemState> BacklogItems { get; set; }
...
}
Repository would use internal constructor in order to instantiate (load) an entity instance from its DB-persisted version.
The one bit I can add myself, is that probably Product domain object should be dirtied with one more accessor just for the purpose of persistence through EF: in the same was as new Product(productState) allows a domain entity to be loaded from database, the opposite way should be allowed through something like:
public class Product
{
// ...
internal ProductState State
{
get
{
// return this.State as is, if you trust the caller (repository),
// or deep clone it and return it
}
}
}
// inside repository.Add(Product product):
dbContext.Add(product.State);
For AssignedOffers : if you look at the code you'll see that AssignedOffers returns value from a field. NHibernate can populate that field like this: Map(x => x.AssignedOffers).Access.Field().
Agree with using CQS.
When doing DDD first thing, you ignore the persistence concerns. THe ORM is tighlty coupled to a RDBMS so it's a persistence concern.
An ORM models persistence structure NOT the domain. Basically the repository must 'convert' the received Aggregate Root to one or many persistence entities. The Bounded Context matters a lot since the Aggregate Root changes according to what are you trying to accomplish as well.
Let's say you want to save the Member in the context of a new offer assigned. Then you'll have something like this (of course this is only one possible scenario)
public interface IAssignOffer
{
int OwnerId {get;}
Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc);
IEnumerable<Offer> NewOffers {get; }
}
public class Member:IAssignOffer
{
/* implementation */
}
public interface IDomainRepository
{
void Save(IAssignOffer member);
}
Next the repo will get only the data required in order to change the NH entities and that's all.
About EVent Sourcing, I think that you have to see if it fits your domain and I don't see any problem with using Event Sourcing only for storing domain Aggregate Roots while the rest (mainly infrastructure) can be stored in the ordinary way (relational tables). I think CQRS gives you great flexibility in this matter.