【问题标题】:EF Navigation Properties not working?EF 导航属性不起作用?
【发布时间】:2013-06-18 03:25:48
【问题描述】:

我有一个 Card 类:

public class Card
{
    public Card(){}

    [Key]
    [Required]
    public virtual int CardId { get; set; }

    [ForeignKey("StageId")]
    public virtual Stage Stage { get; set; }
    public int StageId { get; set; }
    }
}

还有一个舞台类:

public class Stage
{
    [Key]
    public virtual int StageId { get; set; }

    [DataMember(EmitDefaultValue = true)]
    public string Name { get; set; }

    public long Ticks { get; set; }

    [NotMapped]
    public TimeSpan Span
    {
        get { return TimeSpan.FromTicks(Ticks); }
    }

    // Make sure that these stages are generated accordingly
    public static class Ids
    {
        // Zero
        public const int One = 1;
        // Ten Seconds
        public const int Two = 2;
        // One Minute
    }

}

在我的存储库服务中,我有一个 AddCard 方法:

public Card AddCard(Card card)
    {
        int parentId = 0;
        Set parentSet = null;
        if (card.ParentSetId.HasValue)
        {
            parentId = card.ParentSetId.Value;
            parentSet = GetSet(parentId);
        }

        card.ParentSet = parentSet;
        card.ParentSetId = parentSet.SetId;

        card.StageId = Stage.Ids.One;  // Set Id here with hopes of getting card.Stage to resolve as a nav property

        _db.Cards.Add(card);

        SaveChanges();

        return card;
    }

但由于某种原因,我所有的卡片对于 Card.Stage 都有一个空值 - 其中 Card.StageId 始终是某个整数。我正在尝试使导航属性正常工作,以便可以通过卡片访问舞台的属性。

我在这里做错了什么?

更新:

当我尝试通过我的测试访问它们时,该属性为空。首先我创建卡片(在我的测试代码中):

 var cardDto = new CardDto  // Works!
            {
                Details = "Test Card",
            };

然后我将它发送到我的 Dto 服务(也在测试代码中):

 var fullCardDto = _service.AddCard(cardDto); // breaks because Stage is null when stageId is not

CardDto 类:

public class CardDto
{
    public CardDto(){}

    public CardDto(Card card)
    {
        CardId = card.CardId;
        Stage = card.Stage.Name;  // Fails here on its way back - creating the initial DTO works
        Details = card.Details;
    }

    [Key]
    [DataMember(EmitDefaultValue = true)]
    public int CardId { get; set; }


    [DataMember(EmitDefaultValue = true)]
    public string Stage { get; set; }

    [DataMember(IsRequired = false)]
    public string Details { get; set; }

    public Card ToEntity()
    {
        var newCard = new Card
            {
             CardId = CardId,
             Details = Details,
            };
        return newCard;
}

_service 是 DTO 服务:

public CardDto AddCard(CardDto card)
    {
        return new CardDto(_repository.AddCard(card.ToEntity()));
    }

_repository 代码在上面。

这在 _repository 调用中一直有效,但如果我调试 _repository.AddCard 方法,StageId 在我调用 SaveChanges() 后有一个值,但 Stage 没有。

卡被传递回链,直到它应该再次转换为 Dto,由于 null Stage 它失败了。

奇怪的是,这段代码在测试之外工作——如果我使用客户端点击 AddCard,我会得到一张没有任何错误的卡。

【问题讨论】:

  • 你检查数据库数据了吗?它有 Card 的 StageId 值吗?
  • 好的,那你是开启延迟加载还是使用Include?你如何检索舞台?
  • 我没有禁用它,不,不包括。 Stage 是通过 Ids 访问的,如上面的代码所示。我误解你的问题了吗?
  • 你可以给我看一下访问时Stage为null的代码吗?
  • @Jayantha 哦!是的,现在发布

标签: c# .net entity-framework ef-code-first


【解决方案1】:

要使延迟加载工作,您需要创建一个代理。如果您正在加载卡 EF 你会自动收到一个包裹在代理对象中的对象。你可以在这里做两件事
1.对于你使用延迟加载,你可以像这样创建一个代理,

public Card AddCard(Card card)
    {
        var cardProxy= _db.Cards.Create(); 
        //and copy all values from card to cardProxy here..
        int parentId = 0;
        Set parentSet = null;
        if (cardProxy.ParentSetId.HasValue)
        {
            parentId = cardProxy.ParentSetId.Value;
            parentSet = GetSet(parentId);
        }
        cardProxy.ParentSet = parentSet;
        cardProxy.ParentSetId = parentSet.SetId;

        cardProxy.StageId = Stage.Ids.One;  // Set Id here with hopes of getting card.Stage to resolve as a nav property

          SaveChanges();

        return cardProxy;
}
  1. 或者你可以使用显式加载,

    public Card AddCard(卡卡) { int parentId = 0; 设置 parentSet = null; if (card.ParentSetId.HasValue) { parentId = card.ParentSetId.Value; parentSet = GetSet(parentId); }

            card.ParentSet = parentSet;
            card.ParentSetId = parentSet.SetId;
    
            card.StageId = Stage.Ids.One;  // Set Id here with hopes of getting card.Stage to resolve as a nav property
    
            _db.Cards.Add(card);
    
            SaveChanges();
    
            context.Entry(card).Reference(p => p.Stage).Load();//load stage here
    
           return card;
        }
    

【讨论】:

  • 非常感谢。我刚刚在你的博客上发布了一些内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多