EF Core 5 code inheritance without database inheritance #26741 - .net-5

I have two EF models:
public class Child: BaseClass
{
public string SomeProp {get; set;}
}
[Table("TableName")]
public absctract class BaseClass
{
public int ID {get; internal set;}
... some other properties and navigation collections...
}
I have only one table "TableName" with all columns from "BaseClass" and "Child" classes and I would use 'Child' type to access the table.
But, when i've tried to do it, i got exception: "Invalid column name 'Discriminator'."
With EF 6, I was able to do it.

Discriminator is how EF Core differentiates the .Net types in the hierarchy.
Check out the table per heirarchy section in these articles:
https://learn.microsoft.com/en-us/ef/core/modeling/inheritance#table-per-hierarchy-and-discriminator-configuration
https://blogs.dhrutara.com/blogs/efcore5-migrations-with-inheritance/

Related

Validation attributes in external file using MetadataTypeAttribute

I let VS create my model from existing SQL tables using EF 4.3.1. Because the DB tables are not final and may change I don't want to set the validation attributes directly into the model file because it gets overwritten when I update the model.
I want to use the MetadataTypeAttribute approach described here:
Update Model From Database (Database First)
So I created an external file containing this class:
using System.ComponentModel.DataAnnotations;
namespace PDB.Models
{
[MetadataTypeAttribute(typeof(t_scriptingMetadata))]
public partial class t_scripting
{
}
public class t_scriptingMetadata
{
[Required]
public int platform {get; set;}
[Required]
[StringLength(20)]
public string Projectname {get; set;}
}
}
Unfortunately I get these errors in VS:
Duplicate EdmEntityTypeAttribute attribute
Duplicate Serializable attribute
Duplicate DataContractAttribute attribute
My model that has been generated by VS has exactly these attributes the error message mentions:
[EdmEntityTypeAttribute(NamespaceName="CAWI_STDMGTModel", Name="t_scripting")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class t_scripting : EntityObject
{
//...
}
What am I doing wrong?
Your t_scriptingMetadata class have to be into t_scripting not necessarily
[MetadataTypeAttribute(typeof(t_scriptingMetadata))]
public partial class t_scripting
{
public class t_scriptingMetadata
{
[Required]
public int platform {get; set;}
[Required]
[StringLength(20)]
public string Projectname {get; set;}
}
}
And both partial classes must have same namespace.
Hope this help.
Regards
I have found the problem. I had a table in my model that actually is a view containing fields from another table that was also in my model. So the error messages were indeed right. Thank for your help, vfabre!

How to make single controller for two database classes - MVC3

I have two database classes as defined below:
public class TopDate
{
[Key]
public int DateId { get; set; }
public DateTime Date { get; set; }
}
public class TopSong
{
[Key]
public int SongId { get; set; }
public string Title { get; set; }
public int DateId { get; set; }
}
where DateId is foreign key to TopSong
I am creating a controller through which i can create, delete or edit these database values.
When i right click on controller class and add controller i can only select one of the two classes defined above. Is there a way to make 1 controller to handle database updates to both these tables on one page?
Error Image:
Your controller should not be dealing directly with domain objects (meaning those things that are directly associated with your database). Create a ViewModel that contains the properties that you need, use your service layer to populate the ViewModel and your controller will use that as the Model for its base. An example of your ViewModel could be something like the following given your description above:
public class MusicViewModel
{
public int SongId {get;set;}
public string Title {get;set;}
public IEnumerable<DateTime> TopDates {get;set;}
}
This view model would contain a list of all dates that a specific song was a Top Song.
The objects you showing (code) are database classes (so called domain objects).
What you need to do is to define a view model, a standard ASP MVC practice:
you define a class, that is tailored for specific view and only containing data relevant to that particular view. So you will have a view model for a view that will create a song, another that will update it etc.
Actually situation you describing is classical situation to use view models. Using domain objects in the views, however, is really really bad practice and prone to more problems than you want to deal with.
Hope this helps.

Trying to use Entity Framework with asp.net MVC3

I'm trying to make EntityFramework work with ASP .NET MVC3 using this tutorial:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
Ok, I have my database, my .edmx model, model classes but one first thing I don't get is:
How does my DbContext derived class even know my .emdx model ? I don't fine where the "link" is created in this tutorial (maybe having several thing with the same name "SchoolContext", for the context as for the connexionstring is confusing ...)
When I run what I got for now with the code:
MMContext context = new MMContext();
List<EntityUser> testList = (from u in context.Users
select u).ToList();
I get:
System.Data.Edm.EdmEntityType: : EntityType 'EntityUser' has no key defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet �Users� is based on type �EntityUser� that has no keys defined.
Thank you for your help.
Assuming you are using the Code-First approach, you have to define a Key in your Users class:
public class User
{
public int Id { get; set; }
// ...
}
As mentioned from Kyle, if your ID field is not named "Id" you have to add the [Key] attribute:
using System.ComponentModel.DataAnnotations;
public class User
{
[Key]
public int u_Id { get; set; }
// ...
}

How to work with navigation properties (/foreign keys) in ASP.NET MVC 3 and EF 4.1 code first

I started testing a "workflow" with EF code first.
First, I created class diagram. Designed few classes - you can see class diagram here
Then I used EF Code First, created EntsContext..
public class EntsContext : DbContext
{
public DbSet<Project> Projects { get; set; }
public DbSet<Phase> Phases { get; set; }
public DbSet<Iteration> Iterations { get; set; }
public DbSet<Task> Tasks { get; set; }
public DbSet<Member> Members { get; set; }
}
Next step was creating a ProjectController (ASP.NET MVC3) with simple action:
public ActionResult Index()
{
using (var db = new EntsContext())
{
return View(db.Projects.ToList());
}
}
The problem is: I am not getting a ProjectManager in view (List/Create scaffolding used). I would like to know if I am doing this wrong or scaffolding generation just ignores my properties, that aren't basic types.
Hmm... It is probably quite obvious.. because generator doesn't know what property of that Type should be used, right?
Well then I could modify my question a bit: What's a solid way to create a Project entity in this scenario (I want to choose a project manager during project creation)? Should I make a ViewModel for this?
ProjectManager will not be loaded by default. You must either use lazy loading or eager loading. Eager loading will load ProjectManager when you query Projects:
public ActionResult Index()
{
using (var db = new EntsContext())
{
return View(db.Projects.Include(p => p.ProjectManager).ToList());
}
}
Lazy loading will load ProjectManager once the property is accessed in the view. To allow lazy loading you must create all your navigation properties as virtual but in your current scenario it isn't good appraoch because:
Lazy loading requires opened context. You close context before view is rendered so you will get exception of disposed context.
Lazy loading in your case results in N+1 queries to DB where N is number of projects because each project's manager will be queried separately.
I believe you'll need a ProjectManager class, and your Project entity will need to have a property that points to the ProjectManager class.
Something like:
public class Project
{
public string Description {get; set;}
public Member ProjectManager {get; set;}
}

code first approach error: The specified type member 'xxxxx' is not supported in LINQ to Entities

In an effort to further abstract my repository layer I have attempted to follow the code-first approach as described here: http://msdn.microsoft.com/en-us/magazine/ee236639.aspx.
I have a many-to-many relationship between Account and Subscription entities. A Navigation property exists on each entity pointing to the other (e.g. Account.Subscriptions).
Before I created my own model I was using the Entity generated model and the below worked fine ("db" is the entity context) :
public IQueryable<Account> GetBySubscriptionId(int subId)
{
return from a in db.Accounts
where a.Subscriptions.Any(s => s.SubscriptionId == subId)
select a;
}
Now the model for Account looks like this:
public class Account
{
public int AccountId { get; set; }
public string Name { get; set; }
// nav properties
public virtual List<Subscription> Subscriptions { get; set; }
}
And when I try to run the same LINQ query now I get this error:
"The specified type member
'Subscriptions' is not supported in
LINQ to Entities. Only initializers,
entity members, and entity navigation
properties are supported."
Any suggestions greatly appreciated.
Try changing the signature from
// nav properties
public virtual List<Subscription> Subscriptions { get; set; }
to
// nav properties
public virtual ICollection<Subscription> Subscriptions { get; set; }
Shamelessly nicked from Scott Hanselmann's demo here - http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx which uses this pattern, also here's a Scott Guthrie demo using the same idea http://weblogs.asp.net/scottgu/archive/2010/07/23/entity-framework-4-code-first-custom-database-schema-mapping.aspx .
List<T> is a concrete implementation of various interfaces (ICollection, IQueryable, IEnumerable etc), Entity Framework uses proxy objects when it retrieves things from the database, hence the virtual declarations, which use different implementations of these interfaces which is where your error is coming from.

Resources