Very strange issue, I've been using EF + Code First on a lot of projects but I can't figure out what's going on here.
I have the following entities :
public class Article
{
public int ID { get; set; }
public string Title { get; set; }
public virtual Media Image{ get; set; }
public virtual Employee Author {get; set;}
public MyEnum EnumValue {get; set;}
public enum MyEnum {Value1, Value2}
}
public class Media
{
public int ID {get; set;}
public double Length { get; set; }
public string ContentType { get; set; }
public byte[] Content { get; set; }
}
public class Employee
{
public int ID {get; set;}
public string Name{get; set;}
public string Email{get; set;}
}
With the following DbContext :
public class MyContext : DbContext
{
public MyContext() : base("ConnectionString")
{
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = true;
}
public DbSet<Article> Articles { get; set; }
public DbSet<Employee> Employees { get; set; }
public DbSet<Media> Medias { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Article>().HasRequired(x => x.Image);
modelBuilder.Entity<Article>().HasOptional(x => x.Author);
}
}
Nothing special here, however whenever I retrieve an Article for example like that :
var article = _db.Articles.FirstOrDefault(x => x.ID == id);
I have two problems Here is my problem :
The Image navigation property is empty. It is not null but all its properties have default values (0, null, etc...)
The Article object has a dynamic proxy but the navigation properties Image and Employees do not. If I remember correctly, navigations properties should be wrapped by dynamic proxies by default.
One important thing to note is that, the Employee navigation property has all its properties correctly loaded. This is good, however there is no dynamic proxy on it.
I've spent the last 2 hours trying to troubleshoot this and I'm running out of idea.
I would appreciate any hint / help,
Thanks !
Update : I've checked in the database and the foreign key is OK and the record in the Images table does exist.
Not sure I completely understand your question as you're playing a little fast and loose with terms here. Dynamic proxies, in the sense of Entity Framework, are classes that EF creates on the fly that inherit from actual entity classes and override virtual reference and navigation properties to enable lazy-loading. It's not something you really need to pay attention to, for the most part.
Navigation properties are always explicitly added. Entity Framework doesn't not add these for you under any circumstances. Technically what you have is two reference properties on your Article class, and that's it. As a result, Entity Framework creates a proxy of the Article class and returns an instance of that proxy from the results of your query. By attempting to access one of your reference properties, like Image, you activate the lazy-loading logic the proxy class added, causing a new query to be issued to the database to fetch that Media instance. The result will either be the object instantiated with the result of the database query or null. I can't say why you're getting an instantiated Media instance with "default" values. There's nothing regarding Entity Framework that would cause that. You must have some other code interfering with the instance.
As far as Media and Employee go, there's no navigation properties on these classes. If you would like to be able to access the set of related Articles, then you need to add something like:
public virtual ICollection<Article> Articles { get; set; }
Related
Suppose the following structure of classes and relationships:
class Document
{
public List<Version> DocumentVersions { get; set; }
// Other properties
}
class Register
{
public List<Version> RegisterVersions { get; set; }
// Other properties
}
class Version
{
public int VersionNumber { get; set; }
// Other properties
}
When using EF Core, it is going to produce 3 tables, D, R and V respectively where V is going to have 2 FK, one for D and one for R.
My questions are:
Is EF Core default approach correct? Wouldn't it lead to invalid states where V has no FKs because both FKs can be nullable.
I've read this and it almost answered my first question but it leads me to another question:
How can I tell EF to follow that approach: Should I have to create a derived type of V for each of its owners? or is there any way I can map a single entity to multiple tables and tell EF which relationships belong to which table?
Maybe is worth mention that my example is oversimplified and in reality I have 6 entities using the same V entity.
So, the dilemma is:
A) Should I keep two FKs in Version or
B) build two tables DocumentVersion and RegisterVersion instead of just Version?
Well, the truth is you can do both. You just have to decide which approach suits your system better. Let's have a quick look.
Approach A
To answer your question; yes EF's default approach is correct. Among creating two FKs and building two tables, it will create two FKs. It will create an extra table only in case of intermediate table for a many to many relashionship.
I always, though, recommend that we create all FKs ourselves instead of letting EF do it for us. This way we have more control over the behavior of the relationship and can also access the FKs in our application, since they are an entity's property.
public class Version
{
[Key]
public int VersionNumber { get; set; }
public int? DocumentID { get; set; }
public virtual Document Document { get; set; }
public int? RegisterID { get; set; }
public virtual Register Register { get; set; }
//Other properties
}
Since Version has a PK, it can create records without any of the FKs having any value. If this is allowed in your business model then leave it as it is. You can later provide a UI to assign "Versions" to either "Documents" or "Registers".
If you want to add some rules in your Version table; for example each record should have at least one FK or only one FK, you can do that by overriding the ValidateEntity method of your DbContext class (or through some sql constraint in the database probably).
protected override DbEntityValidationResult ValidateEntity(
DbEntityEntry entityEntry, IDictionary<object, object> items)
{
// validate entity from annotations
var result = base.ValidateEntity(entityEntry, items);
// custom validation rules
if (entityEntry.Entity is Version &&
(entityEntry.State == EntityState.Added || entityEntry.State == EntityState.Modified))
{
Version version = ((Version)entityEntry.Entity);
if (version.DocumentID == null && version.RegisterID == null)
result.ValidationErrors.Add(new DbValidationError(null, "A document or register must be specified."));
}
return result;
}
Note that you can create your own annotations to validate your entity properties. But these are restricted to a single property. If you want to add validations that combine more than one property, the ValidateEntity method is the only way I know of.
Approach B
There are two ways to implement this approach. The first is to keep the Version table and add two intermediate tables on top.
public class Document
{
public virtual List<DocumentVersion> Versions { get; set; }
// other properties
}
public class Register
{
public virtual List<RegisterVersion> Versions { get; set; }
// other properties
}
public class Version
{
[Key]
public int VersionNumber { get; set; }
//Other properties
}
public class DocumentVersion
{
public int DocumentID { get; set; }
public virtual Document Document { get; set; }
public int VersionID { get; set; }
public virtual Version Version { get; set; }
// other properties
}
public class RegisterVersion
{
public int RegisterID { get; set; }
public virtual Register Register { get; set; }
public int VersionID { get; set; }
public virtual Version Version { get; set; }
// other properties
}
This actualy allows a many-to-many relationship, but you can use it as a one-to-many.
The second way is to make Version abstract (not a database table) and build two new tables to inherit from Version:
public class Document
{
public virtual List<DocumentVersion> Versions { get; set; }
// other properties
}
public class Register
{
public virtual List<RegisterVersion> Versions { get; set; }
// other properties
}
// don't make this a DbSet
public abstract class Version
{
[Key]
public int VersionNumber { get; set; }
//Other properties
}
public class DocumentVersion : Version
{
public int DocumentID { get; set; }
public virtual Document Document { get; set; }
// other properties
}
public class RegisterVersion : Version
{
public int RegisterID { get; set; }
public virtual Register Register { get; set; }}
// other properties
}
This is a proper and clear one-to-many relationship.
Conclusion
The bottom line is that you can use any of the two approaches and with alterations that suit your needs.
I have used both approaches successfully, but I tend to prefer the second one (and with the abstract class inheritance). The first approach seems more of a way to cut down on database resources or ease of development, but modern databases are not at all stressed by a few tables more and the development could become unnecessarily complex. Further more the second approach allows to extend the functionality of the relationships by adding further properties to each connection table seperatelly. And for the 6 entities you have to deal with, it seems safer to me to go with the second approach. I have used this approach in an application with many file types and relationships and it was always very straight-forward and extendable. Those extra properties in each relashion table came very handy too.
Hope I could help,
merry coding!
I don't think this really is a one-to-many relationship, look here.
It would be a one-to-many relationship if (for example) Document had multiple (e.g. a list of) Versions.
If you want multiple entities refering to the same entity type, you could place the foreign keys explicitly in the Document and Register classes:
class Document
{
public Version DocumentVersion { get; set; }
public int DocumentVersionId { get; set; } // Or whatever datatype your ID is
// Other properties
}
class Register
{
public Version RegisterVersion { get; set; }
public int RegisterVersionId { get; set; } // Or whatever datatype your ID is
// Other properties
}
class Version
{
public int VersionNumber { get; set; }
// Other properties
}
I have an entity called Asset, similar to below:
public class Asset
{
public int Id { get; set; }
public int TypeId { get; set; }
public int AddedById { get; set; }
public DateTime DateTimeAdded { get; set; }
public virtual AssetType Type { get; set; }
public virtual ITUser AddedBy { get; set; }
}
I want to be able to have a navigation property that is linked to a single table, but that table is dependent on what type of Asset it is. For instance, if the Asset is of the type "Printer" then I want the navigation property to link to the PrinterDetail entity. My initial way of going about this was to have unused columns in the Asset entity, but I figured that was wasteful or bad practice. Is there something that I am overlooking or is this just something that cannot be done?
Thanks for any advice given.
if you want navigate printerDetail by type you can use entityfraemwork inheritance strategy:
Table per Hierarchy (TPH)
Table per Type (TPT)
Table per Concrete class (TPC)
you have to create Model per each type and use TPT strategy for that.
and then you can use fluent api for config mapping for that.
parent Model (Asset) must define as abstract class and AssesTypes Must be Drive from the Parent.
more information
I have a parent class ComponentDesign:
public class ComponentDesign
{
public string Name { get; set; }
public virtual JobFile DesignFile { get; set; }
public int? DesignFileId { get; set; }
public Pdf PdfFile { get; set; }
public int? PdfFileId { get; set; }
public JobFile SealedPdfFile { get; set; }
public int? SealedPdfFileId { get; set; }
public int Id { get; set; }
public int JobId { get; set; }
}
And a child class JobFile (of which Pdf is a subclass):
public class JobFile
{
public int ID { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ComponentDesign ComponentDesign { get; set; }
public int? ComponentDesignId { get; set; }
public int? JobId { get; set; }
}
These classes are stored in a relational database using Entity Framework. I would like to have navigation properties on both sides of the relationship, so that I can say componentDesign.PdfFile or jobFile.ComponentDesign at will.
Each property of type JobFile in ComponentDesign is optional, and a JobFile will only ever belong to oneComponentDesign. However, aJobFilemay be free-standing, not belonging to anyComponentDesign(sojobFile.ComponentDesign` would be null).
I'm struggling with how to use the Fluent API to configure this relationship. It is one-to-one. Is it possible to have the navigation properties on both sides of the relationship? Remember that a JobFile can be free-standing (so jobFile.ComponentDesign will not always be relevant), so there are JobFiles that belong to ComponentDesigns and ones that don't. The closest I feel I've come is this:
modelBuilder.Entity<ComponentDesign>()
.HasOptional(componentDesign => componentDesign.DesignFile)
.WithRequired(jobFile => jobFile.ComponentDesign);
But this seems to me to indicate that jobFile.ComponentDesign is always required, which isn't the case. I'm hesitant to just try it because it will generate some substantial migrations, so I wanted to get input first. What should my Fluent API configuration look like for this situation?
Just so that I understand the relationships:
ComponentDesign -> JobFile = Optional.
JobFile -> ComponentDesign = Optional.
This is a Zero-or-one to zero-or-one ([0/1]-[0/1]) relationship.
This can be implemented in the following way, using the the .WithOptionalPrincipal method in fluent API. With a 1-0 relationship, it's obvious which end is the principal end; same with a 1-∞ relationship. ∞-∞ relationships don't have a principal end, due to the hidden tables created that control the relationships between each. With a 0/1-0/1, or a 1-1 relationship, it's not obvious, and so you must tell the database which end to use as the principal end of the relationship. Among many other things, the pricipal is responsible for initiating, and maintaining the relationship between the tables.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure ComponentDesign & JobFile entity
modelBuilder.Entity<ComponentDesign>()
// Mark JobFile property optional in ComponentDesign entity.
.HasOptional(cd => cd.DesignFile)
// Mark ComponentDesign property optional in JobFile entity.
.WithOptionalPrincipal(jf => jf.ComponentDesign);
}
Or, you can create an EntityTypeConfiguration<> class for each entity to separate out the relationships, if there are a lot to sort through. While this does decentralise the relationships, it is more scalable, as these configuration classes can be injected via MEF once the context is configured to do so. Just an idea for future development.
If you were configuring the relationship from the JobFile end, you would use .WithOptionalDependent, in order to set the navigation correctly, instead of .WithOptionalPrincipal. It all depends on which side you configure the relationship from. The ComponentDesign entity relies on the JobFile entity a lot more than the JobFile entity relies on the ComponentDesignentity; thus it should be configured as the principal.
As stated in one of the comments above, complex properties should be adorned with the virtual keyword. This lazy loads the property, and also, when the class is intansiated, it will set the initial value to be null.
Clone the database to a test server, to work on this one problem, then implement the changes on the production model; that way there is no chance of data loss when migrating the database.
I'm new to EF and struggling to implement the following scenario. I have an entity I'd like to have a navigation property to another of the same entity. E.g.
public class Stage {
public int ID { get; set; }
public int? NextStageID { get; set; }
public string Name { get; set; }
public virtual Stage NextStage { get; set;}
}
The only example I've found so far was where the entity had a parent / child relationship, i.e. the navigation property was an ICollection of the same entity. I tried adapting this but couldn't get it to work in my instance. Also, I only need it to be one way, i.e. the entity doesn't have a 'PreviousStage' property, just a 'NextStage' one. I'm configuring using Fluent API. Could someone advise if / how this can be achieved?
I am getting this error:
Unable to determine the principal end of an association between the types 'namespace.Stage' and 'namespace.Stage'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations
Edit
Just realised in my slightly simplified example, I didn't show that NextStageID is optional (int?).
You can explicitly define the relation as follows:
public class Stage {
public int ID { get; set; }
public int NextStageID { get; set; }
public string Name { get; set; }
[ForeignKey("NextStageID ")]
public virtual Stage NextStage { get; set;}
}
you need to add a parentId and Parent navigation property
and Children navigation property so entity framework understands that is a recursive relation
check the answer in this stack Overflow link
I have C# classes that use Inheritance on the server side of a Web API. The base/super class has some 'one two many' navigation properties that are common to all the inherited classes. These classes are not EF or NH classes.
Breeze correctly generates the base class and inherited classes in the metadata and correctly shows the navigation properties from the base class on the inherited classes.
When loading the data from the API, breeze correctly "links" the "Child" -> "Parent" side of the linked navigation property, but does not map the reverse "Parent" -> "Child" relationship on the base class.
If I move the navigation property to the inherited child class, out of the base/super class then Breeze correctly links all the relationships from the Parent to the Child and the Child to the Parent.
public class Fine
{
public int Id { get; set; } // Primary Key
public int VehicleId {get; set; } // Foreign Key
public decimal Amount { get; set; }
... etc
}
public class Vehicle
{
public int Id { get; set; } //Primary Key
... other common properties
public IList<Fine> Fines { get; set; } // Common nav property
}
public class Motorcycle
{
public string MudguardColour { get; set; }
... other specific properties
}
public class MotorVehicle
{
public string BumperColour { get; set; }
... other specific properties
}
Breeze creates the entities on the client side that correctly reflects the shapes above and has ko.observable as well as ko.observablearray for the one to many (Vehicle -> Fines) properties.
If I query the server for the list of MotorVehicles and MotorCycles first, all is well. I then query the list for fines separately and breeze correctly links the "Fines" that are related to a specific Vehicle correctly. I can the say "fine.motorVehicle.id" or "fine.motorCycle.id", depending on the type and get the base/super class properties, like Id as well.
Breeze however does not link the "vehicle.fines", "motorVehicle.fines" nor the "motorCycle.fines" navigation properties. They remain empty arrays even though the "fine" entity is linked correctly to the vehicle, motorVehicle and motorCycle entities.
If I move the navigation property to to the child/inherited class, then breeze correctly links the entities as expected.
public class Fine
{
public int Id { get; set; } // Primary Key
public int VehicleId {get; set; } // Foreign Key
public decimal Amount { get; set; }
... etc
}
public class Vehicle
{
public int Id { get; set; } //Primary Key
... other common properties
//public IList<Fine> Fines { get; set; } // Common nav property
}
public class Motorcycle
{
public string MudguardColour { get; set; }
... other specific properties
public IList<Fine> Fines { get; set; } // Common nav property now in child class
}
public class MotorVehicle
{
public string BumperColour { get; set; }
... other specific properties
}
This gives me "fine.vehicle.id", "fine.motorVehicle.bumperColour" and "fine.MotorCycle.mudguardColour" as well as parent -> child relationship "vehicle.fines[0].amount and "motorCycle.fines[0].amount".
How do I get breeze to set these navigation properties when they are on the base/super class to avoid repeating them on the child/inherited classes?
PS: I am not using EF nor NH, but my metadata is modelled based on the NH layout (from the breeze NH samples) as well as the Breeze documentation with the required foreign keys related etc.
PPS: All of this works 100% for normal classes that do not use the inheritance setup.
Hope I have explained sufficiently?
The solution to the above issue was to ensure that the "associationName" for both the Base class and navigation property classes have the same "association" property "name" within their metadata.
Base Class:
navigationProperties: [{nameOnServer: Fine, entityTypeName: Fine, isScalar: false, associationName: AN_Fine_FineId, invForeignKeyNamesOnServer: [Id]
Related Class:
navigationProperties: [{nameOnServer: Vehicle, entityTypeName: Vehicle, isScalar: true, associationName: AN_Fine_FineId, foreignKeyNamesOnServer: [Id]}]