I would like the below ICollection property in one of my data classes (let\'s call it \"Foo\")
public class Foo
{
[Key]
public int FooId { get; set;
This won't work. The reason for this is, that with relational databases, you can't really save arrays or a collection of things in fields. And since every property in your class will be mapped to a database-field, the only way to collections is via a one to many relationship. So you need the join. So it's not really a limitation of EF, but of relational databases.
There are people that solve that by saving XML or CSV to string fields in the table. But this is considered very bad style, so don't do it. I recommend you just have to accept the join. It's not hurting anyone anyway.
I know this is not best practice in all cases, but I think there are cases where storing a comma seperated list of your array in a column is a good way to solve this problem.
Conditions include:
It could also be a good idea if one entity has multiple string lists in it that would create lots of joins.
In those cases I would solve it by having two properties for the list. One being the comma seperated list used by EF and the other a list that you can use when accessing the items in the list like this:
[NotMapped]
public List<String> AllowedBars { get; set; }
/// <summary>
/// Comma seperated list of AllowedBars
/// </summary>
public String AllowedBarsList
{
get { return String.Join(",", AllowedBars); }
set
{
if (String.IsNullOrWhiteSpace(value))
{
AllowedBars.Clear();
}
else
{
AllowedBars = value.Split(',').ToList();
}
}
}
You need to initialise AllowedBars to be an empty list in the constructor.
You don't need to use the [NotMapped] attribute as this collection won't be used anyway, but I think it makes the intent clearer.
EF can only work with entity classes. Each entity class must have defined primary key so the minimum in your scenario is:
public class StringData
{
public int Id { get; set; }
public string Data { get; set; }
}
or worse
public class StringData
{
[Key]
public string Data { get; set; }
}
Now you can define collection of StringData to map it as related table:
public virtual ICollection<StringData> AllowedBars { get; set; }
You have not define your class tables appropriately. Suppose you have two Tables Foo and FooBar. And there is a one-to-many relationship b/w Foo and FooBar. Then you will define the classes as below.
Foo
public class Foo
{
public int FooId { get; set; }
public string SomeValue { get; set; }
public virtual ICollection<FooBar> FooBars { get; set; }
}
FooBar
public class FooBar
{
public int FooBarId { get; set; }
public string SomeProperty { get; set; }
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
}
This will create two tables with Foo having two columns and FooBar having 3 columns including the FooId depicting one-to-many between Foo and FooBars