I am currently looking for a way I can pass a foreing key to a table entry that is listed in one table,
and should be extracted in another table.
for example purposes I created this ?
public class Parent
{
public string Name {get; set;}
public virtual ICollection<child> Children
Public virtual ICollection<School> Schools {get; set;}
}
public class Child
{
public string Name {get; set;}
Public School Schoola{get; set;} // Which should be a school Name that the Parent Should know?
}
public class School
{
//ParentID
//ChildID
public string SchoolName {get; set;}
}
How do i give my Child instance a SchoolName that the Parent contains within the SchoolNames?
Children and SchoolNames are seperate tables - but child only need to know a specific entry..
Caveat
Your code does not work, since EF does not serialize collections of primitive types. EF Core does have value conversions but it is unclear what you're exactly looking for. I'm going to assume you meant to store these as actual School entities, since your question asks how to "extract one entry from a table".
For the sake of answering your question, I assume that your child should have a reference to the school entity, not a string property that's technically unrelated to the school entity itself, which would make it a question not related to Entity Framework and thus the question tags would be wrong.
I'll address both my assumption and your literal question, just to be sure.
If you need a relationship between a child and a school
From a purely database standpoint, there is no way to specify that an entity's (Child) foreign key should refer to an entity (School) which in and of itself has a foreign key to another entity (Parent). It simply doesn't exist in SQL and therefore EF cannot generate this behavior for you.
What you can do, is implement business validation on your code and refuse to store any child with a school that doesn't belong to its parent. Keep in mind, this requires you to load the parent and their schools every time you want to save a child to the database (because otherwise you can't check if the selected school is allowed for this child), so it will become a somewhat expensive operation.
However, that doesn't prevent the possibility for someone to introduce data into the database (circumventing your business logic, e.g. by a DBA) where this rule is violated but the FK constraint itself is upheld.
How you handle these bad data states is up to you. Do you remove those entries when you stumble upon them? Do you proactively scan the database once in a while? Do you allow it to exist but restrict your application's users to only choosing schools from the parent's scope? These are all business decisions that we cannot make for you.
If a child needs a school name without a relation to the school itself
At first sight, this seems to me to be a bad solution. What happens when the school's name changes? Wouldn't you expect the child's schoolname to also change? Because that's not going to happen in your current setup.
In either case, if you are looking to set a string property, that's trivial, you simply set the property. Presumably, your question is how to restrict the user's options to the child's parent's schools.
This restrictive list can be fetched from the database using the child's identifier:
var childID = 123;
var schoolsFromParent = db
.Children
.Where(c => c.Id == childId)
.Select(c => c.Parent.Schools)
.FirstOrDefault();
Note that this code works regardless of whether you have a School entity or a list of strings - though the type of schoolsFromParent will be different.
And then restrict your end user to only being able to pick from the presented options. Note that to prevent bad data, you should doublecheck the chosen name after the user has selected it.
Related
I have an entity I'm initiating to be saved as a record via EF Core code-first.
Sometimes I will have the related entity model - usually when I'm creating a new related entity at the same time, so it won't have an Id yet.
But sometimes I will only have the ForeignKey Id of the related entity, particularly when I'm adding just this new record related to an existing record.
I haven't been able to find anything on this specific dual-create-mode pattern, is this the correct convention in this situation?
public class ClownModel {
public ClownModel (){}
public ClownModel (CarModel car){
Car = car;
}
public Clown (int carId){
CarId = carId;
}
public int Id {get;set;}
public int? CarId {get;set;}
[ForeignKey("CarId")]
public CarModel Car {get;set;} = null!;
}
My thought is that the FK can be nullable on the entity, so when it's also creating a new related entity it will be assigned during the save?
Long story short, all your reasonable expectations will be met:
If you create a new Clown and assign CarId=1, then EF will assume you know what car you wanted to assign even if it's never seen Car 1 be downloaded before; it will create a Clown with CarId 1. If you have a relationship DB side then Car 1 will need to exist otherwise the DB will reject it
If you create a new Clown and a new Car assigned to its Car property, and that new car has the default value for its CarId, the EF will save the Car first, retrieve the ID and wire it into the Clown before the Clown is saved so that the relationship is satisfied on the DB side
Don't create a new Clown with a new Car that has a CarId that already exists; EF will try to insert a new Car (because it knows the entity is new) with the given ID rather than leaving the DB to create oen, which would probably result in a "cannot insert PK value to a table with IDENTITY_INSERT OFF" type error. If yo uknow the Car Id, use Route 1 above and just assign it to the Clown.CarId
I recommend using one or the other, not both. Typically when you are doing something like creating a row and want to associate another existing row to it, you should explicitly validate that the ID of the associated entity exists to handle things more gracefully than simply waiting for a SaveChanges to fail. Creating a new Clown would pass the details for the clown and a CarId when assigning them to a specific car. In this case my Clown entity would use a Car reference with a shadow property for the CarId. I request the Car from the DbContext via the CarId and handle the situation where a Car might not be found. (Another user deleted it, a bug in the code, or someone is hacking at the request payload)
Alternatively in situations where I either need raw performance or don't care about the entity association, I will just map the Id with no navigation property. Examples of this would be a bounded context that handles background batch-like jobs, or references to FKs that I don't ever need more than the Key for anyways. Such as something like a "Status" where I do have a Status table and FK for referential integrity, but since those statuses have relevance through business logic decisions I would use an enumeration in the code to represent them. I don't care about a Status entity, just it's key.
The reason I don't recommend using both is that it presents a situation where you have two sources of truth. Clown.CarId, and Clown.Car.CarId. If you want to change a clown's car, setting Clown.CarId would have a different behaviour whether Clown.Car was loaded or not. (whether eager loaded, lazy loaded, or populated by the DbContext if it was already tracking the car when the clown was requested)
I'm trying to figure out how to deal with 'Single navigation property case' described in this doc:
Let's say we have 2 models.
class School
{
public ICollection<Child> Childrens {get; set;}
...
}
and
class Child
{
public int Id {get; set;}
...
}
So it's many-to-one relationship created by convention, without explicit foreign key in a Child.
So the question is if we have Child instance and know School.Id is there a way to update this relation without extra call to database to obtain School instance.
So the question is if we have Child instance and know School.Id is there a way to update this relation without extra call to database to obtain School instance.
Yes, it's possible. You can create a fake stub School entity instance with Id only, Attach it to the DbContext (this way telling the EF that it is existing), Attach the Child instance for the same reason, and then add the Child to the parent collection and call SaveChanges:
Child child = ...;
var schoolId = ...;
var school = new School { Id = schoolId };
context.Attach(school);
context.Attach(child);
school.Childrens.Add(child);
context.SaveChanges();
Update: Actually there is another cleaner way, since even if the entity has no navigation or FK property, EF Core allows you to access/modify the so called Shadow Properties
Shadow properties are properties that do not exist in your entity class. The value and state of these properties is maintained purely in the Change Tracker.
as soon as you know the name. Which in your case, without configuration would be by convention "SchoolId".
So no fake School entity instance is needed, just make sure the Child is attached and then simply set the shadow property through ChangeTracker API:
context.Attach(child);
context.Entry(child).Property("SchoolId").CurrentValue = schoolId;
context.SaveChanges();
Based on the updated question
No, there isn't ANY way you could do that by using ORM and strong typing that the ORM offers you, w/o
Two-Way Navigation Property
At least a ForeignKey/Principal property(SchoolId on Child)
Having a shadow foreign key to the parent
performing a raw query (which beats the idea of having ORM for strong typing) and being DB agnostic at the same time
// Bad!! Database specific dialect, no strong typing
ctx.Database.ExecuteSqlCommandAsync("UPDATE Childs SET schoolId = {0}", schoolId);
When you choose to use an ORM you have to accept certain technical limitations of the ORM framework in question.
If you want to follow Domain Driven Design (DDD) and remove all db specific fields form your entities, it won't be easy to use your domain models as entities.
DDD and ORM don't have very good synergies, there are way better approaches for this, but require a different architectural approach (namely: CQRS+ES (Command Query Responsibility Segregation with Event Sourcing).
This works much better with DDD, since the Events from the EventSourcing are just simple (and immutable) message classes which can be stored as serialized JSON in the database and replayed to reconstruct the domain entity's state. But that's a different story and one could write whole books about this topic.
Old Answer
The above scenario is only possible in a single DB operation, if your Child objects a navigation property/"back reference" to the parent.
class School
{
public ICollection<Child> Childrens {get; set;}
...
}
and
class Child
{
public int Id {get; set;}
// this is required if you want do it in a single operation
public int SchoolId { get; set; }
// this one is optional
public School { get; set; }
...
}
Then you can do something like:
ctx.Childs.Add(new Child { Id = 7352, SchoolId = 5, ... });
Of course you first have to know the school Id and know it's valid, otherwise the operation will throw an exception if SchoolId is an invalid value, so I wouldn't recommend this approach.
If you only have the childId and not adding a whole new child you'll still have to get the child first.
// childId = 7352
var child = ctx.Childs.FirstOrDefault(c => c.Id == childId);
// or use ctx.Childs.Find(childId); if there is a chance that
// some other operation already loaded this child and it's tracked
// schoolId = 5 for example
child.SchoolId = schoolId;
ctx.SaveChanges();
I want to separate contact information in my User table, and I am thinking of two ways of doing it.
First is to make a new table and then my User table references that table through foreign key.
Or to make complex type which is part of the User table, by adding [ComplexType] annotation to Address field.
This is Address class, just an example:
public class Address
{
public string City {get; set;}
public string Street { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
}
What do you recommend me to do? Which is better way?
If you ask this quesition for a clean coder then just he will answer you with two entities/classes SRP
http://www.oodesign.com/single-responsibility-principle.html
If you ask the same quesition for a database delevoper then his answer will be no joins use complex types.
Me as a developer I find Complex Types has some limitation and I will never use them.
Here I will copy from http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-2-complex-types the pros and cons of the complex types:
There are three important limitations to classes mapped as Complex Types:
Shared References is Not Possible:
The Address Complex Type doesn’t have its own database identity (primary key) and so can’t be referred to by any object other than the containing instance of User (e.g. a Shipping class that also needs to reference the same User Address, cannot do so).
No Elegant Way to Represent a Null Reference:
As we saw there is no elegant way to represent a null reference to an Address. When reading from database, EF Code First always initialize Address object even if values in all mapped columns of the complex type are null.
Lazy Loading of Complex Types is Not Possible:
Note that EF always initializes the property values of a complex type right away, when the entity instance that holds the complex object is loaded. EF does not support lazy loading for complex types (same limitation also exists if you want to have lazy loading for scalar properties of an entity). This is inconvenient when we have to deal with potentially large values (for example, a property of type byte[] on the Address complex type which has been mapped to a VARBINARY column on Users table and holds an image of the location described by the Address.).
Best Practices you can read it in the given link above.
Well there's no perfect choice for this, it depends on the multiplicity: if a user have multiple addresses then you need to go with the foreign key option, if a user has only one address the you can either add the address fields to the user fields (simple) or use [ComplexType]
Your First (Separate table) choice is better, because single user have multiple contact records then it is better to handle this in separate table by foreign reference.
it is also better for changes in its contact info , means permanent address , postal address , resident contact no , self contact no and so on ,you can easily updated this in separate table ,
and this is the good practice of normalization in database
I noticed something when i was reading through some Entity Framework's POCO classes that the one to many relationship is always represented in two ways like following :
1- Public List<User> Users {get;set;}
2- Public Virtual User Users {get;set}
So which one is right and when i should use each, this concept really confused me !!!
I think you've read that wrong. Typically (although not required), you would have navigation properties at both ends of the relationship.
A collection navigation property on the one side (a Department may have a List<User> for example) and a reference navigation property on the many side (a User would have one Department).
It is also recommended that you have a foreign key property as well, for example an int DepartmentId on the User.
You would need to mark the navigation properties as virtual if you wanted to support lazy loading. See here for the requirements on POCO types.
I'm not well versed in domain driven design and I've recently started created a domain model for a project. I still haven't decided on an ORM (though I will likely go with NHibernate) and I am currently trying to ensure that my Value Objects should be just that.
I have a few VOs that have almost no behavior other than to encapsulate "like" terms, for instance:
public class Referral {
public Case Case { get; set; } // this is the a reference to the aggregate root
public ReferralType ReferralType { get; set; } // this is an enum
public string ReferralTypeOther { get; set; }
} // etc, etc.
This particular class has a reference to "Case" which is two levels up, so if say I were going to access a Referral I could go: case.social.referral (Case, Social and Referral are all classes, there is a single Social inside a Case and there is a single Referral inside a Social). Now that I am looking at it as I type it, I don't think I need a Case in the Referral since it will be accessible through the Social entity, correct?
Now, there is no doubt in my mind this is something that should be a VO, and the method I plan to use to persist this to the database is to either have NHibernate assign it a surrogate identifier (which I am still not too clear on, if anyone could please elaborate on that too it would help me out, since I don't know if the surrogate identifier requires that I have an Id in my VO already or if it can operate without one) and/or a protected Id property that would not be exposed outside the Referral class (for the sole purpose of persisting to the DB).
Now on to my title question: Should a VO have a collection, (in my case a List) inside it? I can only think of this as a one-to-many relationship in the database but since there is no identity it didn't seem adequate to make the class an entity. Below is the code:
public class LivingSituation {
private IList<AdultAtHome> AdultsAtHome { get; set; }
public ResidingWith CurrentlyResidingWith { get; set } // this is an enum
} // etc, etc.
This class currently doesn't have an Id and the AdultsAtHome class just has intrinsic types (string, int). So I am not sure if this should be an entity or if it can remain as a VO and I just need to configure my ORM to use a 1:m relationship for this using their own tables and a private/protected Id field so that the ORM can persist to the DB.
Also, should I go with normalized tables for each of my classes, or not? I think I would only need to use a table per class when there is a possibility of having multiple instances of the class assigned to an entity or value object and/or there is the possibility of having collections 1:m relationships with some of those objects. I have no problem with using a single table for certain value objects that have intrinsic types but with nested types I think it would be advantageous to use normalized tables. Any suggestions on this as well?
Sorry for being so verbose with the multiple questions:
1) Do I need a surrogate identifier (with say NHibernate) for my value objects?
2) If #1 is yes, then does this need to be private/protected so that my value object "remains" a value object in concept?
3) Can a value object have other value objects (in say, a List) or would that constitute an entity? (I think the answer to this is no, but I'd prefer to be sure before I proceed further.)
4) Do I need a reference to the aggregate root from a value object that is a few levels down from the aggregate root? (I don't think I do, this is likely an oversight on my part when writing the model, anyone agree?)
5) Is it OK to use normalized tables for certain things (like nested types and/or types with collections as properties which would need their own tables anyway for the 1:m relationship) while having the ORM do the mapping for the simpler value objects to the same table that belongs to my entity?
Thanks again.
Take a look at the answers to related questions here and here
1) Yes - If you're storing VOs in their own table
2) If you can use a private/protected ID property, then great. Alternatively, you might use explicit interfaces to 'hide' the ID property.
But, reading into your question, are you suggesting that developers who see an ID property will automatically assume the object is an entity? If so, they need (re)training.
3) Yes it can, but with the following restrictions:
It should be quite rare
It should only reference other VOs
Also, consider this: VOs shouldn't stick around. Would it be easy/efficient to re-create the entire VO every time it's needed? If not, make it an Entity.
4) Depends on how you want to implement your Aggregate Locking. If you want to use Ayende's solution, the answer is yes. Otherwise, you would need a mechanism to traverse the object graph back to the Aggregate Root.
5) Yes. Don't forget that DDD is Persistence Ignorant (in an ideal world!).
However...
I believe Referral should be an Entity. Imagine these conversations:
Conversation 1:
Tom: "Hey Joe! Can you give me David Jone's referral?"
Joe: "Which one?"
Tom: "Sorry, I mean Referral No.123"
Conversation 2:
Tom: "Hey Joe! Can you give me David Jone's referral?"
Joe: "Which one?"
Tom: "I don't care - just give me any"
Conversation 1 suggests that Referral is an Entity, whereas conversation 2 suggests it's a VO.
One more thing: Does Referral.ReferralType change during it's lifetime (there's another hint that it should be an Entity)? If it doesn't change, consider using polyporphism and let NH handle it.
Hope that helps!