4

I've been trying to learn EF codefirst. One of the first things is that it won't enforce unique... So... I've tried to solve the problem by exposing a readonly IEnumerble property that forces me to use the AddProp method if I want to add anything to the collection...

When I try to do this (and this is just a "Throw Away" example below) I get the error.

Error 1 The type arguments for method 'System.Data.Entity.ModelConfiguration.EntityTypeConfiguration.HasMany(System.Linq.Expressions.Expression>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. C:\Users\User\Documents\Visual Studio 2010\Projects\ConsoleApplication3\ConsoleApplication3\Program.cs 39 9 ConsoleApplication3

any reason why?

class Program
{
  static void Main(string[] args)
  {
    using (DC _db = new DC())
    {
      PrimeA p = new PrimeA { Name = "BlahGEEEER" };
      p.AddProp(new Prop { comment = "Blah HI!" });
      p.AddProp(new Prop { comment = "Blah HI!" });


      Console.ReadLine();
      _db.PrimeAs.Add(p);
      _db.SaveChanges();
    }
  }
}

public class DC : DbContext
{
  public DbSet<PrimeA> PrimeAs { get; set; }
  public DbSet<PrimeB> PrimeBs { get; set; }
  public DbSet<Prop> Props { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<PrimeA>()
      .HasMany(p => p.Props)  // <---- FAILS HERE
      .WithMany();

    base.OnModelCreating(modelBuilder);
  }
}

public class PrimeA
{

  private List<Prop> m_Props = new List<Prop>();

  public int PrimeAID { get; set; }
  public string Name { get; set; }
  public virtual IEnumerable<Prop> Props
  {
    get 
    {
      return m_Props;
    }

  }

  public bool AddProp(Prop prop)
  {
    bool ret = false;
    var existingResult =
      from p in m_Props
      where p.comment.ToLower() == prop.comment.ToLower()
      select p;
    if (existingResult.Count() == 0)
    {
      m_Props.Add(prop);
      ret = true;
    }
    return ret;
  }
}
Captain Redbelly
  • 280
  • 5
  • 11

3 Answers3

3

As you can see in MSDN, EntityTypeConfiguration.HasMany expects an ICollection<TTargetEntity>. So you have to change Props in

public virtual ICollection<Prop> Props
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
  • Also, usually I don't see private backing fields used either, as EF will use the virtual property to generate a replacement implementation in the proxy object it generates. Instead of using a private backing field, use automatic `{ get;set;}` and initialize the list in the constructor instead of the private field. I'm not sure if this is necessary, but that's based on what I've typical seen/done. – AaronLS May 30 '13 at 23:17
  • I deliberately didn't finish the definition of the property. I think the OP wants to ensure it's never `null`. – Gert Arnold May 30 '13 at 23:22
  • "I think the OP wants to ensure it's never null", yeh and I'm just recommending they do that in the constructor instead, abandon the backing private field, and use automatic getter/setter. Not meant to be a critique of your answer, but an additional suggestion for the OP. Without being able to test, I am just speculating offhand that because of how virtual proxies work, they may not get expected behavior when using a private backing field. – AaronLS May 31 '13 at 00:41
  • I'm trying to disallow the user from entering anything directly unto the collection. What it looks like I'm going to have to do more and more is add an extra layer of abstraction so the user never even sees the database side. I I was hoping to make this simple with out having to do a DAL / BL scenario... but it is looking like this is less of an option. – Captain Redbelly May 31 '13 at 17:10
2

Try using ICollection instead of IEnumerable for your Props property. That should make the error go away.

Here are a couple of posts that help explain why you want to use IList or ICollection instead of IEnumerable.

ICollection Vs List in Entity Framework

Why does the entity framework need an ICollection for lazy loading?

I would also recommend using a HashSet for your private property for Props instead of a List

Community
  • 1
  • 1
DSlagle
  • 1,563
  • 12
  • 19
0

Generic functions have type arguments and they try to "guess"/"infer" the type arguments, but sometimes it is confused and you must specify them explicitly. I don't know the reason why it can't infer in this case, but in your shoes I would try something like, because in this case I think it wants to know the type of the target collection.

.HasMany<Prop>(p => p.Props) 
AaronLS
  • 37,329
  • 20
  • 143
  • 202