【问题标题】:Incorrect database set up, null value on IList数据库设置不正确,IList 上的值为空
【发布时间】:2019-09-13 16:09:42
【问题描述】:

我已将 api 调用中的数据保存到我的数据库中,但在尝试将数据打印到页面时,我得到一个未设置为对象实例的对象引用错误:对象引用未设置为实例的一个对象。我正在尝试访问我的卡片详细信息视图中的 image_url 属性,但它一直在中断

我的模特:

public class Card
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int? Atk { get; set; }
        public int? Def { get; set; }
        public string Desc {get; set;}
        public int? Level { get; set; }
        public string Type { get; set; }
        public string Attribute { get; set; }
        [DisplayName("Image")]
        public IList<Image> Card_Images { get; set; }

        public IList<Deck> Deck { get; set; }
    }

 public class Image
    {
        public int Id { get; set; }
        public string image_url { get; set; }
        public string image_url_small{ get; set;  }
    }

我的控制器操作:

public ActionResult Details(int id)
        {
            var card = _context.Cards.SingleOrDefault(c => c.Id == id);

            if (card == null)
                return HttpNotFound();

            return View(card);
        }

我的数据库表等(在 VS 服务器资源管理器中显示):

Cards
    Id (key sign here)
    Name
    Atk
    Def
    Desc
    Level
    Type
    Attribute

Images
    Id (key sign here)
    image_url
    image_urul_small
    Card_Id

我的看法:

@model YGOBuilder.Models.Card

<div>
    <h4>Card</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Atk)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Atk)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Def)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Def)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Desc)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Desc)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Level)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Level)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Type)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Type)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Attribute)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Attribute)
        </dd>

        <dt>
            @Html.DisplayFor(model => model.Card_Images)
        </dt>

        @foreach (var item in Model.Card_Images)
        {
            foreach (var i in item.image_url)
            {
                <td>
                    <img src=@i height="300" width="200">
                </td>
            }

        }



    </dl>
</div>
<p>
    @Html.ActionLink("Back to List", "Index")
</p>

我正在尝试通过连接到我的模型的 image_url 属性来显示在视图上,但它似乎在这里绊倒了:

 @foreach (var item in Model.Card_Images)

【问题讨论】:

  • Model.Card_Images 中的模型应该小写吗?
  • 没有任何东西可以设置Card_Images。这是代码优先还是数据库优先?
  • @GabrielLuci 这是代码优先 :)
  • @InfiniteHigh 小写不起作用
  • 这两个类由 Id 连接,因此您必须确保模型显示 Id 用于链接两个表。

标签: c# .net database entity-framework


【解决方案1】:

根据the documentation,关系应声明为virtual List&lt;&gt;。我怀疑IList 仍然可以工作,但virtual 更重要。

而且,它还需要知道如何连接表,因此您需要名称匹配的 ID 属性。

public class Card
{
    public int CardId { get; set; }
    public string Name { get; set; }
    public int? Atk { get; set; }
    public int? Def { get; set; }
    public string Desc {get; set;}
    public int? Level { get; set; }
    public string Type { get; set; }
    public string Attribute { get; set; }
    [DisplayName("Image")]
    public virtual List<Image> Images { get; set; }

    public virtual List<Deck> Decks { get; set; }
}

public class Image
{
    public int ImageId { get; set; }
    public int CardId { get; set; }
    public string image_url { get; set; }
    public string image_url_small{ get; set;  }
}

注意ImageIdCardId,以及Image 类中添加的CardId 属性。这就是它如何知道哪个Image 属于哪个Card

您可能必须在 Deck 课程中做同样的事情。

你也在循环item.image_url,这是一个string。效果是循环遍历字符串中的每个字符。你不需要那个内循环。只需在img 标签中使用item.image_url

@foreach (var item in Model.Card_Images)
{
    <td>
        <img src="@item.image_url" height="300" width="200">
    </td>
}

【讨论】:

  • 这种工作,除了现在将空白图像打印到页面上,当我在新选项卡中打开图像时,它会给出错误参数字典包含非参数“id”的空条目-“YGOBuilder.Controllers.CardController”中方法“System.Web.Mvc.ActionResult Details(Int32)”的可空类型“System.Int32”。可选参数必须是引用类型、可空类型或声明为可选参数。参数名称:参数
  • 我更新了我的答案。这就是jdweng所说的。
  • 所以我设法打印出一个工作图像,但是它打印了大约 30 个,查看源它为链接中的每个字符打印出一个图像
  • @GabrielLuci 将关系声明为虚拟关系只是启用延迟加载。此外,CardId 不需要定义关系,授予它更容易,但如果没有定义外键,它会将实体视为影子属性。这基本上意味着实体框架将为此在数据库中创建一个外键属性,但您将无法从模型中直接访问该外键。
  • @AndyStav 如果您已经完成了数据库迁移,我不确定 CardId 是否在做您认为它正在做的事情。虚拟修饰符可能是解决您的问题的原因。不过,您应该注意一件事。通过启用延迟加载,如果您决定在未来序列化数据,您可能只需序列化整个数据库。
【解决方案2】:

您需要在查询中包含集合属性。它不会延迟加载它们。尝试在您的详细信息方法中使用以下内容。

var card = _context.Cards.Include(c => c.Card_Images).Include(c => c.Deck).SingleOrDefault(c => c.Id == id);

这是文档https://docs.microsoft.com/en-us/ef/ef6/querying/related-data。 virtual 修饰符打开延迟加载。因此,仅当您希望每次都延迟加载该属性时才使用它。在某些情况下,这可能会导致请求的信息完全过多。

【讨论】:

  • 我收到 c => c.Card_Images 的错误无法将 lambda 表达式转换为字符串类型,因为它不是委托类型
  • 那是你的看法。在您的视图页面中替换“
    @Html.DisplayNameFor(model => model.Card_Images)
  • 另外,您在 foreach 循环中添加 td 元素而不是 dd 元素
【解决方案3】:
 @foreach (var item in Model.Card_Images)
        {

                <td>
                    <img src=@item.image_url height="300" width="200">
                </td>

        }

public virtual List<Image> Images { get; set; }

public virtual List<Deck> Decks { get; set; }

已修复,感谢大家的意见!

【讨论】:

    猜你喜欢
    • 2017-04-28
    • 2013-11-16
    • 2016-01-02
    • 2018-11-24
    • 1970-01-01
    • 2022-01-02
    • 2012-01-31
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多