I'm starting to use EFCore in a UWP app with SQLite. I've declared the classes that I want stored in the database. I've then declared various DbSets and the OnConfiguring override:
public class DatabaseContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Relationship> Relationships { get; set; }
public DbSet<SourceDescription> SourceDescriptions { get; set; }
public DbSet<Agent> Agents { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<PlaceDescription> PlaceDescriptions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=Testing.db");
}
}
In the Package Manager Console, I then go:
Add-Migration 2017-06-23
and it creates the code to then build the database. HOWEVER, that code is missing some of the top-level tables. Some of them are there but some aren't and I can't see/figure out what is causing this. No errors are generated and I cannot find a pattern to determine why the missing tables are missing.
Further information:
There are 29 classes defined in my code. The migration code creates 24 tables.
Of the 5 "missing" classes, 4 of them are derived from Subject which, in turn, derives from Conclusion. The fifth is the Conclusion class. Since the migration code "merges" the properties from each of the derived classes, I'm not surprised that the Conclusion class doesn't have its own table as there is no direct use of it as a class.
With the exception of the Conclusion class, the other 4 classes are only referenced in the DbSet properties (as opposed to be used in properties in other classes). As noted above, the Document class is derived from another class, so it isn't derived classes that is the common factor.
It isn't that some of the classes are partial classes.
I can't spot anything about the properties in the classes that is a common factor. For example, the Person class has List a couple of times but so does the Agent class and that does appear in the migration code.
Any suggestions on what I can look for or if this is a known issue?
To clarify, the answer provided by Ivan is that EF Core sees the four classes that are derived from the Subject class and builds a table for the Subject class that includes all of the properties for those derived classes. There is then a Discriminator column added to the Subject class that indicates which derived class this is for.
http://www.learnentityframeworkcore.com/inheritance/table-per-hierarchy is a good article for explaining it.
An interesting approach to designing database tables that I hadn't come across before. I live and learn :)
Related
I am EF new learner, i have some questions to ask:
1.
I don't understand what does virtual mean in for example one to many, i give an example:
one question can have many options for e.g.
public class Question
{
public int QuestionId { get; set; }
public string Title { get; set; }
public virtual List<Option> Options { get; set; }
}
public class Option
{
public int OptionId { get; set; }
public string OptionText { get; set; }
public virtual Question Question { get; set; }
}
but what does the "2" virtual mean, because if i delete the virtual in this line:
public virtual List<Option> Options { get; set; }, i didn't find any differences, it works well as one to many, so can you explain me very clearly and easily what the 2 virtual mean, if it's override, override what?
2.
I don't know when we should use API fluent, for e.g. the previous one to many ex. without api fluent, it's still a one to many Relationship, so please just tell me when we should use it ? in which occasions for example.
3.
in the API fluent, i know "withmany" and "hasmany" together, they mean "many to many", and what's "withrequired? isoptional? "
I think I can answer following points:
EF define all navigation property virtual, so that EF will at runtime create a new class (dynamic proxy) derived from your Brand class and use it instead. This new dynamically created class contains logic to load navigation property when accessed for the first time. This feature is called lazy loading (or better transparent lazy loading).
See the following link for more detail
Entity Framework 4.1 Virtual Properties
2.When to use fluent API
When working with Code First, you define your model by defining your domain CLR classes. By default, the Entity Framework uses the Code First conventions to map your classes to the database schema. If you use the Code First naming conventions, in most cases you can rely on Code First to set up relationships between your tables based on the foreign keys and navigation properties that you define on the classes. If you do not follow the conventions when defining your classes, or if you want to change the way the conventions work, you can use the fluent API or data annotations to configure your classes so Code First can map the relationships between your tables.
http://msdn.microsoft.com/en-us/data/jj591620.aspx
3.See the following link to know What is .WithRequired and .WithOptional options
What part does the .WithRequired play in an EF Fluent API?
Is it possible to have Code First data classes declared with internal access as shown:
internal class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
I have a requirement that classes and its properties should not be visible outside of the assembly.
As long as your DbContext derived class that exposes your class to EF is in the same assembly, you should be able to. I don't happen to design my apps that way as I prefer more separation. But the context should be able to build the model and it should be able to interact with the classes (e.g. execute queries, save changes etc) if they are in the same assembly since it will have access to the internal class. Even with the various odd things we tried and wrote about in the Code First book, I never happened to try this particular scenario.
Maybe I haven't quite get the whole thing about models. I tought that, it was probably wrong, EF framework could map any kind of class. So I did provide classes with different interfaces, with ToString() methods and so on.
I was thinking of reusable/flexible structure of classes for some kind of public organization.
For example, there are next classes
[Serializable]
public abstract class AbstractRole
{
public String Title { get; set; }
public abstract void ExecuteRole();
public abstract Decimal GetSalary();
// ToString(...) implementations and so on
}
[Serializable]
public class Employee<T> : IComparable<Employee<T>>, IFormattable where T : AbstractRole
{
private Person person;
public T Role { get; set; }
// interfaces implementations...
}
So all I wanted is to get flexibility to change employee's role in time and not to bind to its instance (avoid inheritance).
But later I read that generics are not supported by EF.
What should I do?
In case of entity framework you must provide exact type. Base classes are supported only if whole inheritance tree is mapped as well. Interfaces and generic types are not supported at all.
That means that reusable and flexible architecture is not something which can use EF.
I'm new to MVC and I'm trying to figure out how to implement business logic in the auto generated Entities in an MVC project.
I know that if I create my own Model class I can put [Required] and other attributes on the fields but there doesn't seem to be an option to do that in the .edmx file.
Is there something I'm missing here?
Should I be creating my own classes that use the entities and put the logic in there?
It seems like there should be a way for me to do less work.
Thanks!
This can be achieved by using the buddy-class functionality in .NET implemented specifically for this reason. Once you have created your entities in your .ebmx file you can create partial classes to accompany your entities which define your business rules in a 'buddy class'.
[MetadataType(typeof(ProductMetadata))]
public partial class Product {
internal sealed class ProductMetadata {
[DisplayName("Name")]
[Required]
public string Name { get; set; }
[DispayName("Price")]
[Required, Range(1,10000)]
public decimal Price { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
}
}
In the example above, assume that you already have a "Product" type defined in your object context which has properties for "Name", "Price", and "Description". So long as the buddy class type referenced by the MetadataTypeAttribute has matching property names, the attributes applied to the properties in the buddy class will be applied to the implementation type.
Note: if there are any property names in the buddy class which do not match the implementation type, you will get a runtime error. You only need to create matching properties in the buddy class for the properties you are interested in applying business rules to; all properties are optional.
I want a list of different (derived) object types working with the Default Modelbinder in Asp.net MVC 2.
I have the following ViewModel:
public class ItemFormModel
{
[Required(ErrorMessage = "Required Field")]
public string Name { get; set; }
public string Description { get; set; }
[ScaffoldColumn(true)]
//public List<Core.Object> Objects { get; set; }
public ArrayList Objects { get; set; }
}
And the list contains objects of diffent derived types, e.g.
public class TextObject : Core.Object
{
public string Text { get; set; }
}
public class BoolObject : Core.Object
{
public bool Value { get; set; }
}
It doesn't matter if I use the List or the ArrayList implementation, everything get's nicely scaffolded in the form, but the modelbinder doesn't resolve the derived object type properties for me when posting back to the ActionResult.
What could be a good solution for the Viewmodel structure to get a list of different object types handled? Having an extra list for every object type (e.g. List, List etc.) seems to be not a good solution for me, since this is a lot of overhead both in building the viewmodel and mapping it back to the domain model.
Thinking about the other approach of binding all properties in a custom model binder, how can I make use the data annotations approach here (validating required attributes etc.) without a lot of overhead?
Check out the Derived Type ModelBinder in MvcContrib. This allows you to modelbind to derived types through the process of 'typestamping' - which is handled automatically for you when using the RenderTypedPartial(...) helper. MvcContrib partials maintain binding state across partials so the Name/Id prefixes are properly maintained on a deep object graph. If you use other mechanisms like templates, then you'll need to handle the typestamping yourself. This is explained in the documentation page.
Getting back to your questions and how the derived types are resolved with the ModelBinder, you can register the derived type variations with attributes in a mechanism similar to the WCF KnownTypeAttribute or you can do the registration on startup. Either way, these variations are registered once and held onto for performance considerations.
The model binder also solves this problem in a way that does not interfere with data annotation/validation attributes. They will work as you expect them in any other scenario.