Не удается сформировать несколько простых POCO для использования с Entity Framework «Code First», пожалуйста, проверьте на ошибку - PullRequest
1 голос
/ 09 октября 2011

Итак, я решил использовать сначала код / ​​DbContext, но уже есть файл базы данных. Ничего сложного, поэтому я думаю, что могу просто создать производный контейнерный класс DbContext с DbSets для соответствующих POCO, создать строку подключения к моей базе данных, и я должен быть установлен. Однако я считаю, что у меня возникают трудности с правильным объявлением свойств в моих классах сущностей, поскольку я получаю ошибки при попытке получить доступ к объекту через навигационные свойства. Обычно говорит мне Object reference not set to an instance of an object, когда я пытаюсь context.Products.Find(1).Category.CATNAME; и т. Д. Также пытался объявить свойства коллекции с виртуальным ключевым словом безрезультатно.

Некоторые особенности схемы базы данных:

В таблице категорий PCATID является внешним ключом для CategoryID в та же таблица категорий и может быть нулевой.

И CategoryID, и RootCategoryID в таблице "Продукты" могут иметь значение null и оба являются внешними ключами для CategoryID в таблице категорий.

В данный момент я тестирую вещи, но со временем для многих полей я буду устанавливать ненулевые типы.

enter image description here

Вот мои POCO сущности и класс контейнера Dbset сущности:

    public class Category
{
    [Key]
    public int CategoryID { get; set; }

    public string CATNAME { get; set; }

    public int PCATID { get; set; }

    public ICollection<Category> Categories { get; set; }

    public ICollection<Product> Products { get; set; }

}


public class Product
{
    [Key]
    public int ProductID { get; set; }

    public int CategoryID { get; set; }

    public int RootCategoryID { get; set; }


    public string Name { get; set; }

    public string ShortDescription { get; set; }

    public string LongDescription { get; set; }

    public string Keywords { get; set; }

    public decimal ListPrice { get; set; }

    public Category Category { get; set; }

}


public class EFDbContext: DbContext
{

    public DbSet<Product> Products { get; set; }


    public DbSet<Category> Categories { get; set; }


}

Ответы [ 4 ]

2 голосов
/ 09 октября 2011

Вам нужно сделать PCATID обнуляемым свойством, так как вы сказали, что оно может быть нулевым.Сделайте все эти свойства навигации и свойства коллекции виртуальными.EF не сможет обнаружить иерархию категорий, поэтому для ее настройки вы должны использовать либо атрибуты, либо свободный API.

public class Category
{
    [Key]
    public int CategoryID { get; set; }

    public string CATNAME { get; set; }

    [ForeignKey("ParentCategory")]
    public int? PCATID { get; set; }

    [InverseProperty("Categories")]
    public virtual Category ParentCategory { get; set; }

    [InverseProperty("ParentCategory")]
    public virtual ICollection<Category> Categories { get; set; }

    public virtual ICollection<Product> Products { get; set; }

}
1 голос
/ 10 октября 2011

Я согласен с @Eranga относительно класса Category (+1 к @Eranga).

public class Category {
    [Key]
    public int CategoryID { get; set; }

    public string CATNAME { get; set; }

    [ForeignKey("ParentCategory")]
    public int? PCATID { get; set; }

    [InverseProperty("Categories")]
    public virtual Category ParentCategory { get; set; }

    [InverseProperty("ParentCategory")]
    public virtual ICollection<Category> Categories { get; set; }

    public virtual ICollection<Product> Products { get; set; }

}

И у вас также есть проблема с вашим запросом Linq:

context.Products.Find(1).Category.CATNAME;

EF возвращает данные только из таблиц, которые вы запрашиваете с помощью Include или используетеэто таблицы в функциях.С этим кодом все работают:

            db.Products
            .Include(p => p.Category) // here I demand to load data from Category table
            .First(p => p.ProductID == 3)
            .Category
            .CATNAME;
1 голос
/ 10 октября 2011

Вы уверены, что действительно хотите использовать Code First? Или вы просто хотите использовать DbContext и DbSet? Вы можете получить те же преимущества с Database First, используя DbContext и DbSet. Поскольку у вас уже есть база данных, она, как правило, намного проще.

См .: http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx

Единственное различие между Code First и Database First с DbContext заключается в том, что Code сначала использует модель отображения с текучей средой, а Database First использует файл .edmx. Поддерживать .edmx намного проще с существующей базой данных.

Если вы обязаны использовать Code First, тогда я предлагаю получить Power Tools CTP1 для Entity Framework и выполнить обратный инжиниринг вашей базы данных в Code First.

1 голос
/ 09 октября 2011

Требования для создания прокси POCO

Все выглядит готовым для POCO, но Lazy Loading не разбирается на этом этапе. По умолчанию LL включен, но для того, чтобы включить отложенную загрузку, свойство Category должно быть виртуальным (создается прокси, который перехватывает ссылку и загружает данные). Если вам не нужна отложенная загрузка, отключите ее в конструкторе EFDbContext.

Итак, ваши варианты:

public virtual Category Category { get; set; } 

или

public class EFDbContext: DbContext 
{
    public static EFDbContext()
    {
        LazyLoadingEnabled = false
    }
    ...
}

Возможно, вы захотите сделать первый ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...