This question is about the navigation property in an EF generated entity.
I am trying to improve my ability to more loosely couple code and have run into a problem understanding the navigation property that is so useful when using EF entities. I am working with the code first methodology. The code that follows is my best attempt to simulate the issue to keep the code presented here tightly focused on my question. While we can sometimes omit something critical when we do this, because the problem I am struggling with is present below, I think the simulation is OK.
Using the following architecture with the class definitions that follow, there is a navigation property layer1 in the layer2 entity. In this architecture, layer1/layer2 interface directly with SQL.
Public Class layer1
Public Property ID As Integer
Public Property name As String
Public Overridable Property layer2 As New List(Of layer2)
End Class
Public Class layer2
Public Property ID As Integer
Public Property name As String
Public Property layer1ID As Integer
Public Overridable Property layer1 As layer1 <<<< navigation property
End Class
Public Class efTestingContext
Inherits DbContext
Public Sub New()
MyBase.New("name=efTestingContext")
Configuration.ProxyCreationEnabled = False
End Sub
Public Property layer1 As DbSet(Of layer1)
End Class
This image shows what the layer1 entity looks like after SQL data retrieval.
It can be seen that the layer2.layer1 property is in fact a layer1 type, which makes sense.
Now the following classes dlayer1/dlayer2 are added to simulate a domain layer and simulate the different architecture also shown.
Public Class dlayer1
Public Property ID As Integer
Public Property name As String
Public Overridable Property layer2 As New List(Of dlayer2)
End Class
Public Class dlayer2
Public Property ID As Integer
Public Property name As String
Public Property layer1ID As Integer
Public Overridable Property layer1 As dlayer1 <<<< navigation property
End Class
End Class
This requires what I assume is often called a DTO (?) to convert layer1 to dlayer1. This simulated conversion object is shown below.
Function Index() As ActionResult
Dim theLayers = db.layer1.Include("layer2").ToList()
Dim thedLayers As New List(Of dlayer1)
'This code simulates the storage to domain translation
For Each layer In theLayers
Dim aLayer As New dlayer1
aLayer.ID = layer.ID
aLayer.name = layer.name
For Each subLayer In layer.layer2
Dim aSubLayer As New dlayer2
aSubLayer.ID = subLayer.ID
aSubLayer.name = subLayer.name
aSubLayer.layer1ID = subLayer.layer1ID
aSubLayer.layer1 = subLayer.layer1 <<<< something else needs to happen. What?
aLayer.layer2.Add(aSubLayer)
Next
thedLayers.Add(aLayer)
Next
Return View(theLayers)
End Function
The code above returns, of course, the following:
How do I code this so that the navigation property will be properly created in the dlayer1 entity?
I am aware of libraries such as automapper, but that seems to be focused on the domain-to-presentation interaction. I am not aware of libraries that handle the data-to-domain interaction. But even if there is a library that would do this, I’d still like to know how I would discretely code this. I'm also assuming this question is equally applicable to the equivalent C# code.
Navigation properties often don't survive an implicit DTO mapping, because they are prone to recursion. Converting layer1 to dlayer1 also converts the underlying layer2 to dlayer2, each of which then convert their layer1 to dlayer1, and you have created infinite recursion.
There are some ways around this, but the easiest way is to simply ignore the nav props, and later recreate them based on the PK/FK properties.
As an aside, this issue in unrelated to EF. It's related to the inability of implicitly handling circular references. Circular references generally lead to recursion, and .NET doesn't really protect you from unwanted recursion. It only raises an issue once the stack actually overflows at runtime.
Either empty the nav props, or make sure that your mapping does not try to map the nav props.
Convert each object to its equivalent DTO class. There should be no problem, as they are no longer linked to any other object (or their links are being ignored by the mapping process)
Recreate their navigational properties by matching dlayer1.ID to the dlayer2.layer1ID property.
That is the easiest way to get around it, and the performance cost of doing so is negligible.
Update for the questions in your comment.
Regarding point #3 - that's simply storing the parent ID value and not, as point #1 seems to say, recreating a nav prop.
Maybe I explained it badly. Let me show a quick example. Note that the code is massively oversimplified for the sake of brevity.
1 - Either empty the nav props, or make sure that your mapping does not try to map the nav props.
foreach( var child in myChildren ) { child.Parent = null; }
myParent.Children = null;
2 - Convert each object to its equivalent DTO class. There should be no problem, as they are no longer linked to any other object (or their links are being ignored by the mapping process)
foreach( var child in myChildren )
{
myDtoChildren.Add(child.ConvertToDTO());
}
myDtoParent = myParent.ConvertToDTO();
3 - Recreate their navigational properties by matching dlayer1.ID to the dlayer2.layer1ID property.
foreach( var dtoChild in myDtoChildren )
{
dtoChild.Parent = myDtoParent;
}
myDtoParent.Children = myDtoChildren.Where(c => c.ParentId == myDtoParent.Id);
In other words; you temporarily deleted the nav prop (the link to the other object), but you retained the foreign key (the ParentId property).
After mapping, you then use the ParentId (FK) property to fill in the Parent (nav prop) property.
But you also said there are some ways around this. Can you elaborate?
The example above is essentially a workaround. You edit the data to avoid the problem. But there are other ways to avoid the problem.
For XML serialization, you can add a [XmlIgnore] attribute to the nav prop so it does not get mapped (therefore preventing recursion).
WCF data contracts actually don't run into recursion problems here, they are able to handle circular references.
If you use explicit mapping rules (as opposed to implicit ones), you can simply omit the nav prop from the mapping.
Related
[ Follow up from this question Should entity have methods and if so how to prevent them from being called outside aggregate ]
I am trying to understand in full details how aggregate root exposes data from its child entities to outer world; in particular, at least repository will need that info in order to be able to save it.
So, for the sake of the argument, lets consider these rules:
Person have a few channels of communication: phone, email, facebook account (might as well be a collection of each of those but for simplicity lets say its just one of each).
Person can choose to make any of those channels public so that other Persons can contact him or make any of those private so that he can't be pinged through that particular channel.
Person can choose global setting of not being contacted at all. In that case, its forbidden to switch any of the phone, email, facebook to public.
[ Note: the model i'll show now might not be the best one but lets leave remodeling aside for now and focus on exposing child entity infos ]
lets say we have aggregate root Person (c# code), only with example for Phone entity as others are the same logic:
class Person {
...
private Phone Phone { get; set;}
public bool WantsToBeContactedAtAll { get; }
public void ExposePhoneNumberPublic() {
if(!this.WantsToBeContactedAtAll)
throw new SomeError("Not allowed.");
this.Phone.PublishPhoneNumber(true);
}
public void HidePhoneNumber() {
this.Phone.PublishPhoneNumber(false)
}
}
class Phone {
//this is identifier
public readonly string PhoneNumber { get; private set; }
public string Description { get; private set; }
public boolean ShouldBePublished { get; private set; }
public Phone(string phoneNumber, string description, bool shouldBePublished) {
//set values
}
public void PublishPhoneNumber(bool preference){
this.ShouldBePublished = preference;
}
So, what we want to prevent is someone doing:
Person Adam = new Person(...);
Adam.Phone.PublishPhoneNumber(true);
But now, we still need info from Adam.Phone if for nothing else, then for the repository to access it when saving aggregate:
_personRepository.Add(Adam);
Questions:
How to expose Person.Phone info?
Should we expose some copy of the Phone property as a struct (value object)?
Have Phone as private type within Person aggregate and expose another PhoneReadOnly type what would be just a class with properties and getters.
Another way of asking those all question is: how can at least repository read Person.Phone information that it needs in order to be able to save Person?
Please treat me as a complete idiot and explain in details.
Thanks
How shoud aggregate expose info from child entity?
In a way that doesn't allow the caller to change the state of the aggregate.
Pass a primitive value
Pass a reference to an immutable object
Pass a copy of an object
Copies of information are fine, because you can't change my state by changing your copy of my data. References to immutable objects are fine, because you can't change them at all, therefore you can't change my state. But giving you a reference to my mutable state increases the odds of a programmer error.
Let's consider the repository example for a moment -- repositories, remember, are used to give the application the illusion that all of the aggregates are just members of some vast, in memory collection. To support this illusion, the repository needs two functions -- one that takes a representation from our stable data store and creates from it the domain model entities that make up the aggregate, and another that takes the aggregate and constructs from it the representation to put in the data store.
Let's pretend that we had some really naive aggregate that was just an array of integers
class Aggregate {
int [] State;
}
And then we imagine the functions that a repository might need to load and store this aggregate
Aggregate a = Aggregate.from(state)
int [] state = a.state
Now, what happens if we try to cheat?
int [] state = a.state;
state[0] = 12345;
Did a change? Since we want the domain model to be the authority for the state of the world, the answer had better be "no". Which in turn means that the aggregate doesn't yield a reference to its own array, but instead a copy of that array.
The same principle applies if we think about an aggregate with an array of child entities.
class Aggregate {
Child [] children;
}
So what does this aggregate yield? Not it's own array, because that would allow the client to change the aggregate by replacing a Child. But it can't just copy the array either, because we could call methods on one of the child array elements to change itself, which would indirectly change the state of the aggregate.
So we don't return an array of children, we return an array of descriptions of children. It's a sort of "deep copy". The descriptions contain copies of data, but no references -- nothing that links back to the internals of the entity itself -- and so it is safe to yield the description to a caller, who can do what they like with it (including sticking the description into a document store for later recovery).
I tend to think that making your child entities (immutable) value objects simplifies this issue a lot.
A rule of thumb is that you never modify a value object, you replace it. Unlike controlling what people do with the inside of your sub-entities, assigning a value to a direct property of the AR is something you can easily restrict from the root. You can just mark the setter as private and only allow changing it by going through the adequate AR method:
class Person {
public Phone Phone { get; private set; }
public void ExposePhoneNumberPublic() {
if(!this.WantsToBeContactedAtAll)
throw new SomeError("Not allowed.");
Phone = new Phone(Phone.Number, Phone.Description, shouldBePublished: true);
}
}
Note that the part where you take the existing Phone and new up a slightly different one could be done more elegantly - see the "with" keyword here.
Another way of asking those all question is: how can at least
repository read Person.Phone information that it needs in order to be
able to save Person?
I believe that's actually a totally different question. Usually, reading is not the hardest part - if you want any client code to be able to read the Phone, there's no reason that a Repository won't. Writing can be more tricky, as a well-encapsulated aggregate root doesn't necessarily let you change it like that. With ORMs, making the setters protected will work most of the time. An alternative is to use internal with InternalsVisibleTo the concrete repository's assembly, or work with a fully mutable backing state object.
I'm new at WPF and I'm trying to use MVVM. I'm using CollectionViewSource in my view-model against a SQL database using Entity Framework.
So let's say I have this class:
public class People
{
public int Id { get; set; }
public string name { get; set; }
}
And lets say this is what I have in the database:
ID: Name:
Bugs Bunny
Mick Jagger
Mickey Mouse
Donald Duck
Goofy
Elmer Fudd
Daffy Duck
Porky Pig
Now using CollectionViewSource.View, I know how to use the methods MoveCurrentToNext(), MoveCurrentToPrevious(), etc. and that works fine, but I need to move to a specific name, for example Donald Duck. So if I do this:
dbContext.Peoples.Find(4);
Or if I do this
dbContext.Peoples.Where(p => p.Name == "Donald Duck").FirstOrDefault();
That will get me the right object from the database using Entity Framework. However, if I do this:
CollectionViewSource.View.MoveCurrentTo(dbContext.Peoples.Find(4));
It will not move, and CollectionViewSource.View.CurrentItem is null.
So then how would someone move to the correct item?
I guess this is because the reference that you get when calling dbContext.Peoples.Find(4) is not the same as the one you have in your CollectionView source collection.
The CollectionViewSource.View.MoveCurrentTo (an others 'MoveTo' methods of the collectionView) requires an argument that is the same reference as the one in your source collection.
Then, if your dbContext methods to retreive an object returns a new instance or an instance different than the one in your CollectionView, this won't work.
So either use an intermediate collection as the source of the collection view to keep a unique reference to the objects (and update these references when the object in in data access context change) or try to implement equality members in your People class (never tried the later solution but should work).
Also, try to add in your question some complete piece of code rather than code fragments about which we can't realy see exactly where is the problem.
I am currently using Entity Framework for a project and one of my classes have an Enum representing some values.
So far EF is saving the Enums as numbers in the database, but I wanted to save them as their actual string names. For example, the Enum NY is saved as 1, instead of "NY".
I have already seen some ways to make this work, like having a string property with a hidden Enum private field, but I wanted to know if there is a way I can just Intercept EF when it's doing the CRUD operations and then I can change the Enum to a String in the Data Context class.
No, you cannot do that directly: when you map your class with an Enum property, that property is mapped to a database int column, and you cannot change that in any way. I mean that, as you cannot change the model, there is no way to intercept and convert the Enum property value into an string, because the model stubbornly wants an int.
That said, there are several ways to make it work:
having an string property for the key and a [NotMapped] Enum property that updates that key. SEE THE NOTE: But the key must be public, and thus accesible through the application code.
using a class that have only the enum property and is used in your application domain, and a different class which is used for your EF model, and map the values, for example using ValueInjecter or Automapper
I usually take the first path and use an attribute that allows me to define the string key for each Enum value, so you can reuse this pattern in all the cases in which need to do this.
NOTE: this part of the answer was wrong: you can map any property regardles of the modifier (public, protected, private, internal...). EF conventions only include the public properties, and there are no data annotations that can overcome this limitation. But you can use it with the Fluent API. However, as the property is private,you cannot access it directly using the Fluent API. There are several solutions to do it described here: Code First Data Annotations on non-public properties
If you follow this path, you can have a class like this:
public class MyEntity
{
// ...
[NotMapped]
public EnumType Value
{
get { /* return KeyForEnum converted to EnumType value */ }
set { /* set KeyForEnum value from the received EnumType value*/}
}
// Use some mechanism to map this private property
private string KeyForEnum { get; set; }
// ...
}
As you can see, if you use a class like this, in the app the entity will have a property of EnumType type, but in the database it will be an string.
One of the tricks to be able to map it through Fluent API is this:
1) Add an static property that returns an expression able to select the property from an object of this class, i.e.
public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression
= me => me.KeyForEnum;
2) Use it in the fluent API to get the property mapped, like so:
modelBuilder
.Entity()
.Property(MyEntity.KeyForEnumExpression)
LAST NOTE: This will modify the POCO class by adding the static readonly property. You can use Reflection instead to build an expression to access the private property, like you can see here: EF 4.1 Code First, ¿map private members?. It's in Spanish, but you can look directly at the code
I have a complex object using inheritence that I map with automapper, it maps perfectly during a get request, but during a post request the exact same code doesn't map the inerited types correctly.
Let me explain. (See code below)
In the first case when I map the object during a simple get request, it maps perfectly fine and the Parent property of the class A below is of its specific type B or C.
But when the exact same mapping happens during a post, the Parent property of A is of type A!??
Now, the code is the same, the data model coming back from the DB is the same. (I use nhibernate - and the types are as I expect) the only difference is that it is a post request?!
Is there something I should know about AutoMapper in this case?
Class definitions (ViewModels follow the same structure):
public class A
{
public A Parent { get; set;}
}
public class B : A
{ }
public class C : A
{ }
And mapped like this:
CreateMap<A, AViewModel>()
.Include<B, BViewModel>()
.Include<C, CViewModel>();
CreateMap<B, BViewModel>();
CreateMap<C, CViewModel>();
Calling map:
var aModel = _aManager.Get("same parameter");
var aViewModel = Mapper.Map<AViewModel>(aModel);
Edit #1 - This depicts the logic in the post Action:
[Transaction] // Commits the nhibernate transaction on OnActionExecuted
[HttpPost]
public ActionResult UpdateA(OtherModelViewModel viewModel)
{
var a = _aManager.Get("same parameter");
var otherModel = Mapper.Map<OtherModel>(viewModel);
a.AddOtherModel(otherModel);
_otherModelRepository.New(otherModel);
// Eeek, writing this out I am seeing a problem here, I suspect this is where my problem would be, loading the model again from the db, after updating it in session without commiting it? I am going to change the logic and see if it fixes it.
var aModel = _aManager.Get("same parameter");
var aViewModel = Mapper.Map<AViewModel>(aModel);
// return result.
}
Sorry I was being silly and letting the complexity get the better of me.
I use a transaction attribute, to persist the information in OnActionExecuted.
So what I was doing was > loading the model > modifing it > then loading it again and trying to map it before it had even been persisted.
I know that nHibernate really doesn't like it when you try and do things like that, so I think the in memory object graph was in a state of flux (pending commit), which was affecting the mapping.
I have change my logic to rather do an ActionRedirect after the update, which has resolved the mapping issue.
Much happier all around.
In a question about Best practices for C# pattern validation, the highest voted answer
says:
I tend to perform all of my validation in the constructor. This is a must because I almost always create immutable objects.
How exactly do you create an immutable object in C#? Do you just use the readonly keyword?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
Would it look like below?
public partial readonly Person
{
public Person()
}
The interesting question here is your question from the comments:
What kind of object would you have that you do not need to modify the values at some point? I'm guessing not a model class, correct? I've had to change the name of a person in my database - this wouldn't fit with this idea.
Well, consider things that are already immutable. Numbers are immutable. Once you have the number 12, it's 12. You can't change it. If you have a variable that contains 12, you can change the contents of the variable to 13, but you are changing the variable, not the number 12.
Same with strings. "abc" is "abc", and it never changes. If you have a variable that contains "abc", you can change it to "abcd", but that doesn't change "abc", that changes the variable.
What about a list? {12, "abc"} is the list that is 12 followed by "abc", and that list never changes. The list {12, "abcd"} is a different list.
And that's where things go off the rails. Because in C# you can do it either way. You can say that there is referential identity between those two lists if lists are allowed to mutate their contents without changing their identity.
You hit the nail right on the head when you talk about the "model". Are you modeling something that changes? If so, then it is possibly wise to model it with a type that changes. The benefit of that is that the characteristics of the model match the system being modeled. The down side is that it becomes very tricky to do something like a "rollback" functionality, where you "undo" a change.
That is, if you mutate {12, "abc"} to {12, "abcd"} and then want to roll back the mutation, how do you do it? If the list is immutable you just keep around both values and choose which one you want to be the "current" value. If the list is mutable then you have to have the undo logic keep around an "undo function" which knows how to undo the mutation.
As for your specific example, you certainly can create an immutable database. How do you change the name of someone in your immutable database? You don't. You create a new database that has the data you want in it. The trick with immutable types is to do so efficiently, without copying billions of bytes. Immutable data structure design requires finding clever ways to share state between two nearly-identical structures.
Declaring all fields readonly is a good step towards creating an immutable object, but this alone is not sufficient. This is because a readonly field can still be a reference to a mutable object.
In C# immutability is not enforced by the compiler. You just have to be careful.
This question has two aspects:
Immutable type when you instantiate object
Immutable type when EF instantiate object
The first aspect demands sturcture like this:
public class MyClass
{
private readonly string _myString;
public string MyString
{
get
{
return _myString;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
}
Now the problem - EF. EF requires parameterless constructor and EF must have setters on properties. I asked very similar question here.
Your type must look like:
public class MyClass
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
private set
{
_myString = value;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
// Not sure if you can change accessibility of constructor - I can try it later
public MyClass()
{}
}
You must also inform EF about private setter of MyString property - this is configured in properties of enitity in EDMX file. Obviously there will be no validation when EF will materialize objects from DB. Also you will not be able to use methods like ObjectContext.CreateObject (you will not be able to fill the object).
Entity Object T4 template and default code generation create factory method CreateMyClass instead of constructor with paremeters. POCO T4 template doesn't generate factory method.
I didn't try this with EF Code first.
An immutable value object is a value object that cannot be changed. You cannot modify its state, you have to create new ones
Check out Eric Lippert's blog:
Kinds of Immutability
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability
Have a look at
Immutable object pattern in C# - what do you think?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
It wouldn't work in this context because EF requires the properties of the entity class be public otherwise it can't instantiate it.
But you're welcome to use immutable objects further in your code.
C# 9 is coming up with new feature names as Record. Init-only properties are great if you want to make individual properties immutable. If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record:
public data class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
The data keyword on the class declaration marks it as a record.
Reference: https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#records
#Eric Lippert Good comment, but in addition in answer to the question:
What kind of object would you have that you do not need to modify the
values at some point? I'm guessing not a model class, correct? I've
had to change the name of a person in my database - this wouldn't fit
with this idea.
Let's say you have a large datastructure and you want to query its information, but it's changing all the time. You need some kind of locking system to make sure that you don't say try and count the total in the system while somebody is depositing something from one place to another. (Say a warehouse management system)
And that's hard to do because these things always affect things in unexpected ways, the data changing under your feet.
What if you could freeze your large datastructure when you're not updating it, so that no memory can be altered and it is paused at a consistent state? Now when you want to change it again you have to copy the datastructure to a new place, and it's fairly large, so that's a downside, but the upside is you won't have to lock anything because the new copy of the data goes unshared until it has been updated. This means anyone at any point can read the latest copy of the datastructure, doing complex things.
So yep very useful concept if you hate dealing with concurrency issues and don't have too much data to deal with. (E.g. if 1MB of data and updating 10/sec that's 10MB of data being copied)