How to handle custom fields in Entity Framework 6.0? - entity-framework

Consider this scenario:
Table1
Field1
Field2
Field3
We are writing an ERP application and it is common for implementations have additional fields based on user needs say User1 and User2 to Table1. Information about these user fields is stored in metadata tables. Custom fields will differ from one implementation to other.
I am wondering if EF can support this requirement.
Ideally I would like to have model classes generated like
partial class Table1
public Field1 {get; set;}
public Field2 {get; set;}
public Field3 {get; set;}
///The user fields collection should store user defined fields
public List<string, object) UserFields {get; set;}
When I say context.Table1.Get("foo"), system should return appropriate data
Is this possible in EF?
regards,
Abhishek
I could not find relevant examples. I can modify template files so that all entities can have additional property public List<string, object) UserFields {get; set;}. But I have no idea how EF can recognize additional user fields and hydrate entities accordingly. Any help will be greatly appreciated.

Related

Entity Framework Core Many-to-Many Implementation

So Many-to-Many did not make it into .NET Core 3.0 release, bummer...
I'm aware of how to implement m:m using a join entity as in this example: https://stackoverflow.com/a/53972658/980917
My question is about the model classes themselves. Consider Student & Class example:
Student - has ICollection<StudentClass>
StudentClass - joining entity
Class - has ICollection<StudentClass>
That is fine for data loading purposes. But in your business logic collection of StudentClasses is not useful as its just a joining entity with 2 IDs. When working with Student or Class you actually want an actual collection of Classes inside a Student and a collection of Students inside a Class. (ie: Student.Classes & Class.Students.
What's the current recommended approach / workaround to retrieve the many-to-many collections (not joining entity)?
Do we have to do a 2nd select based on on the joining entity or is there something more elegant?
A quick example or a link would be great. Thanks.
What's the current recommended approach / workaround to retrieve the many-to-many collections (not joining entity)?
You can do easily with .Include extension method as follows:
Lets say your Student class as follows:
public class Student
{
public int Id {get; set;}
public string StudentName {get; set;}
public ICollection<StudentClass> StudentClasses {get; set;}
}
To retrieve all the students with their associated classes:
var studentsWithClasses = _context.Students.Include(s => s.StudentClasses).ToList();
To retrieve a single student with its classes:
var studentWithClasses = _context.Students.Where(s => s.Id = studentId).Include(s => s.StudentClasses).FirstOrDefault();

Why is Entity Framework looking for the wrong foreign key column?

I've seen various questions on related topics, which seem like they would address my issue, but nothing I try seems to help.
I have an EF (6.1.3) model of an existing DB, which has been working fine. I've just added an additional column to a table, which represents a new relationship. Perhaps relevantly, the relationship is the second one between the two tables - the original Location is now joined by ActualDirectSite, both of them relating the Uniform and Location tables.
The moment I added the two new properties, ActualDirectSiteID and ActualDirectSite, my SELECT queries started failing with the error "Invalid column name 'Location_ID'". It's true that that column doesn't exist, but I don't see why EF is looking for it - it was happy before, but something has made it think the column name should be different. The failing name makes me think it's the original Location which is somehow no longer working.
Here's the Entity in question:
public partial class Uniform
{
public int ID { get; set; }
[Column("LocationID")]
public int? LocationID { get; set; }
[ForeignKey("LocationID")]
public virtual Location Location { get; set; }
public int? ActualDirectSiteID { get; set; }
[ForeignKey("ActualDirectSiteID")]
public virtual Location ActualDirectSite { get; set; }
}
And my (shortened) table def:
CREATE TABLE [dbo].[Uniforms](
[ID] [int] IDENTITY(1,1) NOT NULL,
[LocationID] [int] NULL,
[ActualDirectSiteID] [int] NULL)
The obvious solution to relying on convention causing incorrect assumptions about column names is to specify them explicitly, and so I've tried using Column annotations, and also to make sure that the ID and navigation properties know about each other using ForeignKey, but no dice. Any ideas?
EDIT: added missing LocationID field (already present in full code)
EDIT2: to be clear, before I added ActualDirectSiteID to the Entity it all worked fine, with no annotations required. I've just had another look at the generated SQL, and it seems like the Location_ID reference corresponds to the ActualDirectSite property:
//[Extent1] is "Uniform"
... , [Extent1].[LocationID] AS [LocationID], [Extent1].[ActualDirectSiteID] AS [ActualDirectSiteID], [Extent1].[Location_ID] AS [Location_ID], //...[Extent4] begins
EDIT3: I didn't include any of my Location entity, here it is:
[Table("Location")]
public partial class Location
{
public int ID { get; set; }
public virtual ICollection<Uniform> Uniforms { get; set; }
}
As noted in the comments: with multiple navigation properties to the same table, EF will get confused as to which navigation property refers to which inverse navigation property and ignore the FK mapping of those. A similar issue I stumbled across some time ago can be found in this SO question.
There are only two ways (I know of) to fix this issue:
Ignore at least all but one of the navigation properties with [NotMapped] or .Ignore() or
Add a inverse navigation property to (at least) all but one navigation properties to this table and adjust the mapping accordingly.
Actually, this behavior smells like a bug on EF side (from a DB point of view, I don't see the problem there), but the workaround is simple enough.
By convention every foreign key declaration include 2 properties.
If you create link to Location entity, then you must add property with name - LocationId type int. That is why you got an error
ForeignKey annotation is used to specify the name of used int id property for link (if you plan to use different name)
You can declare foreign key only like here:
public Location Location {get; set;}
public int LocationId {get; set;}
Or like here:
[ForeignKey("CustomIdProperty")]
public Location Location {get; set;}
public int CustomIdProperty {get; set;}
(Pardon me for possible typos - writting from phone)

Entity Framework: Map join tables

I have the following model:
I want to expose a member on "intallations" that give me a list of "modules" based on the join table "installation_modules", how can I do that ?
I want to be able to write
installations.Modules.Something()
Without having to use the join table in my code.
I also want to map "installation_type" directly on the installation, is it possible ? If yes how ?
Entity Framework will automatically manage the many-many relationship for you, but usually the installation_modules table should be having just two columns, installation_id and module_id which will be the composite primary key instead of a separate primary key. So Installation model/class will have public virtual ICollection<Module> Modules {get; set;} and the Module class will have public virtual ICollection<Installation> Installations {get; set;}navigational properties for easy accessing of entities.
I also want to map "installation_type" directly on the installation, is it possible ? If yes how ?
Yes, it is possible. You can have a navigational property for InstallationType in your Installation entity for this.
public class Installation
{
//....other properties
[Column("installation_type_id")]
public int InstallationTypeId {get; set;}
[ForeignKey("InstallationTypeId")]
public virtual InstallationType InstallationType{get; set;}
}

Entity Framework Migration to Update existing many-to-many to 2x one to many

I've an existing relationship between two entities (many-to-many). Let's say something like this:
public class TypeA
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<TypeB> TypeBs {get;set;}
}
public class TypeB
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<TypeA> TypeAs {get;set;}
}
Entity Framework generates a table for the many-to-many as an internal. However, I would like to add custom properties to this generated table. I've read some other questions/answers where they say: create a new entity and do one-to-many from both existing entities to the new entity. Of course this will work, but I'm not sure what the best way is to add a migration in a way that Entity Framework let's me keep the generated table without loosing data.
Any ideas?

Different types of Users with simplemembership in ASP.NET EF code first

In my app I want to have two different types of users. This types differ not only in role but also in attributes. I am using simpleMembership for userManagement and I want to ask what's the best way or practise to create data model for my situation in EF using code first. I was thinking about creating two another tables UsersType1 and UsersType2 which will have one to one relationship with table userProfiles so in the model I would have:
public class UserType1{
attr1
attr2
....
public int userProfileID {get; set;}
public virtual UserProfile userProfile {get; set;}
}
And same way for table UserType2.
I want to ask if this is a good way to go and if so, how should I modify userProfiles table to be able to access UserType1 and UserType2 through userprofile in code.
Thank you.
Use "Roles" to group users of the same type. Then use a custom table with the roleid as key.
I guess you could use inheritance, so UserType1 would inherit from UserProfile.
public class UserType1 : UserProfile
{
attr1
attr2
}
and when you fetch the UserProfile from the database you should be able to cast it to a UserType1 to access the attributes.