Relationship - EF Core

.net c# entity-framework-core

Question

I'm having some trouble to get into EF Core relationship.

I didn't know how to search it properly, so I've not found what I need, but I got somewhere.

I have these two classes:

Expense:

public class Expense : Entity
{

    public string Title { get; set; }
    public string Description { get; set; }
    public decimal Amount { get; set; }
    public List<ExpenseType> Types { get; set; }
    public ValidationResult ValidationResult { get; private set; }

    public bool IsValid
    {
        get
        {
            var fiscal = new ExpenseIsValidValidation();
            ValidationResult = fiscal.Valid(this);
            return ValidationResult.IsValid;
        }
    }}

ExepenseType:

 public class ExpenseType : Entity
{
    #region properties
    public string Name { get; private set; }
    public string Description { get; private set; }
    public ValidationResult ValidationResult { get; private set; }
    public bool IsValid
    {
        get
        {
            var fiscal = new ExpenseTypeIsValidValidation();
            ValidationResult = fiscal.Valid(this);
            return ValidationResult.IsValid;
        }
    }}

During the ToListAsync in ExpenseType, the EF adds the column "expenseId" to the query, but this column does not exist.

My database has three tables, one for each class, and one for the relationship. (Expense, ExpenseType and Expense_ExpenseType)

By looking for the solution here on StackOverflow I found that I should have a class for the third table. Here it is:

 public class Expense_ExpenseType
{
    public int ExpenseId { get; set; }
    public Expense Expense { get; set; }
    public int ExpenseTypeId { get; set; }
    public ExpenseType ExpenseType { get; set; }
}

My idea is that I can have an ExpenseType without having an Expense, and I can have an Expense without ExpeseType or with as many as I want of them.

So ExpenseType hasn't any Expense.

I'm not sure what I should do now. Should I Map using optionsBuilder? How? Should I ReWrite the database?

1
2
2/18/2019 1:56:42 PM

Accepted Answer

If you want to create Many-to-Many relationship, you have several options how to do it:

  1. Create additional class how you described. In this case EF will create table and you can get access to get values only from this table.

    public class Expense_ExpenseType
    {
       public int ExpenseId { get; set; }
       public Expense Expense { get; set; }
       public int ExpenseTypeId { get; set; }
       public ExpenseType ExpenseType { get; set; }
    }
    
  2. You may don't create class and just describe in the context relationship. Where you will describe everything and EF will create by yourself this table. But from the app you will not see this table. You have to use this variant if you don't want to extend table with additional fields.

     modelBuilder
       .Entity<Student>()
       .HasMany<Course>(s => s.Courses)
       .WithMany(c => c.Students)
       .Map(cs =>
         {
           cs.MapLeftKey("StudentRefId");
           cs.MapRightKey("CourseRefId");
           cs.ToTable("StudentCourse");
         });
    

For this relationship you can read more here

But in your case you don't need to use Many-to-Many. That's why if you don't want to add propertie ExpanseTypeId or ExpenseId in your model you can describe it like this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<Expense>()
     .HasMany<ExpenseType>(o => o.Types) //It is your list of expense types.
     .WithOne() //Here you can add model for expense. To have an option go back from expense type to expense
     .HasForeignKey("ForeignKey");//This key EF will create for you in DB but not in you app model
}

What do you want to use you have to decide. If you have an idea that expense has a lot of expensetypes and each expense type has a lot of expenses. You have to use Many-To-Many how I described.

0
2/18/2019 5:02:10 PM

Popular Answer

I think that your main question is "My idea is that I can have an ExpenseType without having an Expense, and I can have an Expense without ExpeseType or with as many as I want of them."

so you can do that by creating a nullable foreign key ExpenseTypeId in Expanse class and HashSet of Expanse in ExpeseType class.

Like this:

public class ExpenseType : Entity
{
 public ICollection<Expanse> Expanses {get; set;} = new HashSet<Expanse>()
}

public class Expense : Entity
{
 public int? ExpanseTypeId {get; set;}
 public ExpanseType ExpanseType {get; set;}
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow