Entity Framework, Unneeded Foreign key - entity-framework

I'm using EF Code first.
I created two classes. For simplicity, imagine that I have a User table (class) and a FileAttachment table. I want to use the FileAttachment table with many other classes, so that any part of the application that requires having a FileAttachment can reuse that table. The problem is that when EF generates the schema, it creates a Foreign Key in the FileAttachment table back to User table. Is there a way to disable that?
Thanks

You need to build an intermediate class.
public class UserDocument
{
public int Id {get;set;}
public int UserId {get;set;}
public virtual User User {get;set;}
public int FileAttachmentId {get;set;}
public virtual FileAttachment FileAttachment {get;set;}
}
So your user class can now have:
public virtual ICollection<UserDocument> Documents {get;set;}
And in this case, FileAttachment class will not have reference to User.
If you want now to build some other document type, just implement another intermediate type, i.e. imagine you want to have CustomerDocument:
public class CustomerDocument
{
public int Id {get;set;}
public int CustomerId {get;set;}
public virtual Customer Customer {get;set;}
public int FileAttachmentId {get;set;}
public virtual FileAttachment FileAttachment {get;set;}
}
And then your hypothetical Customer class would have:
public virtual ICollection<CustomerDocument> Documents {get;set;}

Related

ChangeTracker doesn't show navigation property changes in Entity Framework

I have the below structure in Entity framework
[Table("Person")]
public class Person
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public long Id{get ;set;}
public string Name{get;set;}
public long DId { get; set; } // this is id from Department Table
[ForeignKey("DId")]
public Department SudentDepartment{get;set;}
}
[Table("Department")]
public class Department
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public long Id{get ;set;}
public string Name { get; set; }
}
Now, I am overriding the SaveChanges method to Audit changes in Audit Table at field level. I am unable to get old and new value of Department in ChangeTracker as it is navigation property. This is required because in Audit table I need to save Departname instead of Id.
Is there any way I could get the navigation property in ChangeTracker?
Only input I have is that you could try to use a code similar to the one on Audit.EntityFramework library.
Check the GetForeignKeysValues code here:
https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.EntityFramework/EntityKeyHelper.cs#L145

Entity Framework Code First - Setting Foreign Key / Navigation Property

I like to reference to a specific entry in a database. Is there a data annotation, which I could use
E.g.
public class Address
{
public int CityId {get; set;}
}
public class City
{
public int id {get; set;}
}
So the Address.CityId references the City.id.
And how can I reference to Table Columns via data annotations.
Please refer this link .
https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
in that read Topic : The Key Attribute
What you want is called One-To-One entity mapping. You can create navigation property in your Address class as follows:
public class Address
{
[Key]
public int AddressID {get;set;}
public int CityID {get; set;}
[ForeignKey("CityID")]
public City City {get;set;}
}
public class City
{
[Key]
public int CityID {get; set;}
}
Add ForeignKey attribute to your navigation property to create mapping through foreign key. And do not forget to define key attributes in each EF model.
More details on Entity Framework home page: Configure One-to-Zero-or-One Relationship

Map Parent-Child in Hierarchy with Entity Framework

We are using Entity Framework and We have one unique requirement, and after trying many possible options, I couldn't figure out how I can do that, below is the problem summary.
I have following Entity
public class SuperParent
{
[Key]
public int SupoerParentId {get;set;}
public virtual ICollection<Parent> Intermediates {get;set;}
}
public class Parent
{
[Key]
public int ParentId {get;set;}
[ForeignKey("SuperParentId")]
public virtual SuperParent Ancestor {get;set;}
public int SuperParentId {get;set;}
public virtual ICollection<Child> Children {get;set;}
}
public class Child
{
[Key]
public int ChildId {get;set;}
[ForeignKey("ParentId")]
public virtual Parent Ancestor {get;set;}
public int ParentId {get;set;}
/// Area of guidance required here..............
/// I just want to some what denormalize table and add SuperParentId also in
/// Child and in Database. As most of time its child we query and its very
/// efficient for us to directly query based on SuperParentId, I want to do
/// something like below:
[ForeignKey("SuperParentId")]
public virtual SuperParent Ancestor {get;set;}
public int SuperParentId SuperAncestorId {get;set;}
}
We have 1:N:N relationship, and many times we just want to bypass Parent and from SuperParent to directly want to reach to Child... Currently multi level joins are having problem and our query are not efficient, we store large amount of data and each table has 20+ columns.
Questions:
Is it possible with EF? then how I can write modelBinder
OnModelCreating to support this?
Any other alternative?
If you want to have that kind of design, then by default Child will have cascade delete from Parent and SuperParent, which is not allowed in sql.
public int SuperParentId { get; set; } // -> non nullable
If a foreign key on the dependent entity is not nullable, then Code
First sets cascade delete on the relationship. Source
You can simply remove the default cascade delete from SuperParent.
modelBuilder.Entity<Child>()
.HasRequired(c => c.Ancestor)
.WithMany()
.WillCascadeOnDelete(false);
If you have Child collection on SuperParent, mention it when calling WithMany.
public DbSet<Child> Children { get; set; }
Change above WithMany with
.WithMany(sp => sp.Children)

EF Using FK's for 1:1 Relationships

when working with my POCO objects, I prefer to delay instantiation of navigation properties as much as possible (performance reasons). Instead I'd like to use the FK Value on my entities.
For Example:
class Car
{
public int Id {get;set;}
public int RegistrationId {get;set;}
public virtual Registration Registrations {get;set;} // Nav Property
}
class Registration
{
public int Id {get;set;}
public int CarId {get;set;}
public virtual Car Car {get;set;} // Nav Property
}
Given this is a 1:1 Relationship, how can I get EF to populate my FK Values for me? (using EF 6.0.1)

Provide Entity Framework hints about how / what order to cascade delete

I am doing a Code-first EF approach except for the fact that I am managing the database (for schema change issues that I believe still exist in code-first). I have the following tables / model objects (eliding several parameters, etc) :
class A {
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual List<B> BList {get;set;}
public virtual List<C> CList {get;set;}
}
class B {
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("A"), Required]
public int AId {get; set;}
public virtual A parent {get;set;}
public virtual List<D> DList {get;set;}
}
class C {
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("A"), Required]
public int AId {get;set;}
[ForeignKey("someD"), Required]
public int someDId {get;set}
public virtual D someD
}
class D {
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("B"), Required]
public int BId {get;set;}
public string data {get;set;}
}
There's more to it than that, but the idea is that from a parent object A, I can navigate to a D along two different relationships. The Cascade delete relationships in the database are set up such that A->B, A->C, and B->D are cascades; C->D is 'no action'.
Therefore, when I go to delete an A (DbSet.Remove(a); SaveChanges(); etc ) EF needs to delete the C branch first, so that it can later delete the D's and not violate the FK constraint C->D. However, it appears to be choosing the other path, as the delete throws an exception about said constraint being violated. Is there a way for me to provide a hint (attribute or otherwise) to EF to tell it something else about these relationships so it can delete things in the right order?
edit Added more clarity to the approach in the code; Also, this thought occurs to me: I'm not explicitly capturing the relationship from C->D on D's end - that is, there is no navigation property on D that points to C; because C is a part of a Table-per-type scheme and not all D's point to a good collection of C's base class. Do I need to have some kind of navigation property in D back to C for EF to understand what I want?