Entity Framework Code First - Relationships

2019-07-29 18:39发布

I am trying to add relationships to my entities using EF Code First in Web API project

My Database Seed code is

internal class ProductDbInitializer : DropCreateDatabaseAlways<ProductDbContext>
{
    protected override void Seed(ProductDbContext context)
    { 
        Category category = new Category();
        LanguagesDbContext languagesDbContext = new LanguagesDbContext();
        List<Language> languages = new List<Language>
        {
            new Language {Name="English",Code="en" },
            new Language {Name="Italian", Code="it" },
            new Language {Name="Russian",Code="rus" },
        };

        languagesDbContext.Languages.AddRange(languages);

        context.Categories.Add(category);

        List<CategoryText> categoryText = new List<CategoryText>();

        foreach (var language in languages)
        {
            string name = string.Empty;

            switch (language.Code)
            {
                case "en":
                    name = "paper";
                    break;
                case "it":
                    name = "carta";
                    break;
                case "rus":
                    name = "бумага";
                    break;
                default:
                    name = "paper";
                    break;
            }

            categoryText.Add(new CategoryText
            {
                Category = category,
                Language = language,
                Name = name
            });
        }

        category.CategoryTexts.Add(categoryText[1]);
        context.CategoryTexts.AddRange(categoryText);

        context.SaveChanges();
    }
}

everything is stored in DB and I think problem in declaration of my classes, because when I want to get Categories I have not able to see CategoryTexts

this is output in browser

output in browser

but in database I have my CategoryTexts added with valid CategoryId.

this is my Category and CategoryText Entities

public class Category
{
    public Category()
    {
        CategoryTexts = new List<CategoryText>();
    }

    public int Id { get; set; }
    public ICollection<Product> Products { get; set; }
    public ICollection<CategoryText> CategoryTexts { get; set; }
}

and

public class CategoryText
{
    public int Id { get; set; }
    public int CategoryId { get; set; }
    public int LanguageId { get; set; }

    [ForeignKey("CategoryId")]
    public Category Category { get; set; }

    [ForeignKey("LanguageId")]
    public Language Language { get; set; }
    public string Name { get; set; }
}

Please help me to understand where do I need to change code

1条回答
神经病院院长
2楼-- · 2019-07-29 19:12

You need to either eager load your relationships (using Include when you query), for example:

var myList = context.Products.Include("Categories").Include("CategoryTexts").ToList();

Or you can explicitly load them (with context.Entry(x).[Reference|Collection](x).Load(), for example:

var myProduct = context.Products.First();
context.Entry(myProduct).Collection(x => x.Categories).Load();

Or:

var myCategoryText = context.CategoryText.First();
context.Entry(myCategoryText).Reference(x => x.Language).Load();

Or you can have them auto-load (lazy loading) using proxies... but for that, your foreign entities and collections must be marked virtual in your POCOs:

public class Category
{
    public Category()
    {
        CategoryTexts = new List<CategoryText>();
    }

    public int Id { get; set; }
    public virtual ICollection<Product> Products { get; set; }
    public virtual ICollection<CategoryText> CategoryTexts { get; set; }
}

and

public class CategoryText
{
    public int Id { get; set; }
    public int CategoryId { get; set; }
    public int LanguageId { get; set; }

    [ForeignKey("CategoryId")]
    public virtual Category Category { get; set; }

    [ForeignKey("LanguageId")]
    public virtual Language Language { get; set; }
    public string Name { get; set; }
}

You also need to have proxy creation and lazy loading turned on, but that's the default in EF6.

Also remember that the context must be "alive" (not disposed) when accesing the properties so that there's a live context where they can be loaded

Link to related documentation: https://msdn.microsoft.com/en-us/data/jj574232.aspx

查看更多
登录 后发表回答