Question

I have two entities Task and Attempt, One task has many Attempt, so I defined the entities as below.

public class Task
{
    public long TaskId { get; set; }
    [Required]
    public int DestinationNumber { get; set; }
    [Required]
    public int CountryCode { get; set; }
    // blah blah
    public virtual ICollection<Attempt> Attempts { get; set; }
}

public class Attempt
{
    public long Id { get; set; }
    public string AttemptsMetaData { get; set; }
    public DateTime Time { get; set; }
    public bool Answered { get; set; }
    public DateTime Disconnected { get; set; }
    // foreign key
    public long TaskId { get; set; }
    public virtual Task Task { get; set; }
}

I used Code First Relationships Fluent API to map the relationship.

public class OutboundContext : DbContext
{
    public DbSet<Task> Tasks { get; set; }
    public DbSet<Attempt> Attempts { get; set; }
    public OutboundContext()
        : base("Outbound")
    {
        Database.SetInitializer<OutboundContext>(new CreateDatabaseIfNotExists<OutboundContext>());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Task>().HasMany(t => t.Attempts).WithRequired();
    }

Unit test was passed but when I check the table [Outbound].[dbo].[Attempts]. The columns are

   [Id]
  ,[AttemptsMetaData]
  ,[Time]
  ,[Answered]
  ,[Disconnected]
  ,[Task_TaskId]
  ,[Task_TaskId1]

You see first [Task_TaskId] is wrong and one more extra column [Task_TaskId1] was generated.

What is wrong?

EDIT:

TaskId should be the foreign key.

// Add dummy data
        public bool AddAttempt(List<Attempt> attempt)
        {
            using (OutboundContext db = new OutboundContext())
            {
                foreach (var item in attempt)
                {
                    db.Attempts.Add(item);
                }
                try
                {
                    db.SaveChanges();
                    return true;
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return false;
                }
            }
        }

        List<Attempt> attempts = new List<Attempt>();
        Attempt objAtt = new Attempt();
        long id = 123456789;
        objAtt.AttemptId = id;
        objAtt.Time = DateTime.Now;
        objAtt.AttemptsMetaData = "test";
        objAtt.Answered = true;
        objAtt.Disconnected = DateTime.Now;
        objAtt.TaskId = 33333333;
        attempts.Add(objAtt);
        //Then call AddAttempt
Was it helpful?

Solution 2

Using Fluent API.

modelBuilder.Entity<Task>().HasMany(t => t.Attempts).WithRequired(t=>t.Task).HasForeignKey(t => t.TaskId);

The other point is that we have to save the tables in correct order. Something like:

            db.Tasks.Add(task);
            db.SaveChanges();
            Attempt a = new Attempt() { Id = Guid.NewGuid(), TaskId = task.TaskId, AttemptsMetaData = "1" };
            db.Attempts.Add(a);
            db.SaveChanges();

Otherwise it shows "invalid column" on TaskId in SQL Server Management Studio.

OTHER TIPS

It seems that the problem happened because the Collection of Attempt you have in the Task class is not being actually referenced to the "Task" property you are having in the Attempt class. My suggestion is to clearly declare a int TaskId property in the Attempt class and do the mapping in the following way for Attempt Class:

HasRequired(attempt => attempt.Task)
            .WithMany(task => task.Attempts)
            .HasForeignKey(attempt => attempt.TaskId);

Hope this helps.

I made a very small change to the OnModelCreating and its not creating a an additional [Task_TaskId1] in the database:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Task>().HasMany(t => t.Attempts);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top