Это мой первый раз, когда я использовал Entity Framework 6.1 (сначала код). Я продолжаю сталкиваться с проблемой, когда мои свойства навигации имеют значение null, когда я не ожидаю, что они будут. Я включил ленивую загрузку.Entity Framework 6.1: свойства навигации не загружаются
Моя сущность выглядит следующим образом:
public class Ask
{
public Ask()
{
this.quantity = -1;
this.price = -1;
}
public int id { get; set; }
public int quantity { get; set; }
public float price { get; set; }
public int sellerId { get; set; }
public virtual User seller { get; set; }
public int itemId { get; set; }
public virtual Item item { get; set; }
}
Она имеет следующий картограф:
class AskMapper : EntityTypeConfiguration<Ask>
{
public AskMapper()
{
this.ToTable("Asks");
this.HasKey(a => a.id);
this.Property(a => a.id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(a => a.id).IsRequired();
this.Property(a => a.quantity).IsRequired();
this.Property(a => a.price).IsRequired();
this.Property(a => a.sellerId).IsRequired();
this.HasRequired(a => a.seller).WithMany(u => u.asks).HasForeignKey(a => a.sellerId).WillCascadeOnDelete(true);
this.Property(a => a.itemId).IsRequired();
this.HasRequired(a => a.item).WithMany(i => i.asks).HasForeignKey(a => a.itemId).WillCascadeOnDelete(true);
}
}
В частности, проблема заключается в том, что у меня есть Ask
объекта правильно установить itemId
(что соответствует к Item
в базе данных), но свойство навигации item
равно null, и в результате я получаю исключение NullReferenceException. Исключение в коде ниже, когда я пытаюсь получить доступ a.item.name
:
List<Ask> asks = repo.GetAsksBySeller(userId).ToList();
List<ReducedAsk> reducedAsks = new List<ReducedAsk>();
foreach (Ask a in asks)
{
ReducedAsk r = new ReducedAsk() { id = a.id, sellerName = a.seller.username, itemId = a.itemId, itemName = a.item.name, price = a.price, quantity = a.quantity };
reducedAsks.Add(r);
}
Смутно, навигация свойство seller
работает отлично там, и я не могу найти что-нибудь, что я сделал по-другому в «User «сущность», ни в своем картографе.
У меня есть тест, который воссоздает, но она проходит без каких-либо проблем:
public void canGetAsk()
{
int quantity = 2;
int price = 10;
//add a seller
User seller = new User() { username = "ted" };
Assert.IsNotNull(seller);
int sellerId = repo.InsertUser(seller);
Assert.AreNotEqual(-1, sellerId);
//add an item
Item item = new Item() { name = "fanta" };
Assert.IsNotNull(item);
int itemId = repo.InsertItem(item);
Assert.AreNotEqual(-1, itemId);
bool success = repo.AddInventory(sellerId, itemId, quantity);
Assert.AreNotEqual(-1, success);
//add an ask
int askId = repo.InsertAsk(new Ask() { sellerId = sellerId, itemId = itemId, quantity = quantity, price = price });
Assert.AreNotEqual(-1, askId);
//retrieve the ask
Ask ask = repo.GetAsk(askId);
Assert.IsNotNull(ask);
//check the ask info
Assert.AreEqual(quantity, ask.quantity);
Assert.AreEqual(price, ask.price);
Assert.AreEqual(sellerId, ask.sellerId);
Assert.AreEqual(sellerId, ask.seller.id);
Assert.AreEqual(itemId, ask.itemId);
Assert.AreEqual(itemId, ask.item.id);
Assert.AreEqual("fanta", ask.item.name);
}
Любая помощь будет очень ценится; это заставляло меня сходить с ума в течение нескольких дней.
EDIT:
База данных SQL Server 2014.
На данный момент я один общий контекст, инстанцирован уровень выше этого (мое хранилище слой для БД). Должен ли я создавать новый контекст для каждого метода? Или создание экземпляра на минимально возможном уровне (т. Е. Для каждого доступа db)? Например:
public IQueryable<Ask> GetAsksBySeller(int sellerId)
{
using (MarketContext _ctx = new MarketContext())
{
return _ctx.Asks.Where(s => s.seller.id == sellerId).AsQueryable();
}
}
Некоторые из моих методов вызывают другие на уровне репо. Будет ли лучше для каждого метода принимать контекст, который он может передать любым методам, которые он называет?
public IQueryable<Transaction> GetTransactionsByUser(MarketContext _ctx, int userId)
{
IQueryable<Transaction> buyTransactions = GetTransactionsByBuyer(_ctx, userId);
IQueryable<Transaction> sellTransactions = GetTransactionsBySeller(_ctx, userId);
return buyTransactions.Concat(sellTransactions);
}
Тогда я мог бы просто создать экземпляр нового контекста всякий раз, когда я называю что-нибудь из слоя репо: repo.GetTransactionsByUser(new MarketContext(), userId);
Опять же, спасибо за помощь. Я новичок в этом и не знаю, какой подход был бы лучшим.
Wat - это срок службы контекста (ов)? И какая это база данных? –
Спасибо, что посмотрели. Я отредактировал вопрос, чтобы дать дополнительную информацию. –