【问题标题】:access [NotMapped] property with a custom getter/setter使用自定义 getter/setter 访问 [NotMapped] 属性
【发布时间】:2016-03-21 12:18:04
【问题描述】:

我有一个包含文件夹的数据库,我将文件夹的整个路径存储为folder_name 等等。喜欢://MainFolder/subFolder/folderName。在我的应用程序中,我有一个名为 Folder 的模型,它代表 db 中的文件夹。

型号:

 public class Folder
 {   
    [Key]
    public string folder_name { get; set; }
    [NotMapped]
    public string folder_name_short
    {
       get
       {
           string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/")); //System.NullReferenceException here
           return shortname;
       }
       set
       {
           string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
           this.folder_name = folder_name.Replace(shortname, value);
       }
    }
 }

folder_name_short 没有被映射,因为它只是整个路径的一个子字符串,所以我不想存储它两次。我的意思是示例:

Console.WriteLine(folder_name)          output://MainFolder/subFolder/folderName
Console.WriteLine(folder_name_short)    output:/folderName

在我的视图中,用户可以重命名文件夹。所以我想将旧的folder_name_short 替换为新的,并将新的字符串存储在folder_name

查看:

.
.
using (Html.BeginForm("Rename", "Folders", FormMethod.Post))
{
    @Html.EditorFor(model => model.folder_name_short)
    <input type="submit" value="rename folder" id="submit" class="btn btn-default" />
}
.
.

问题: Inputtextbox 在其中呈现并显示folder_name_short 的当前值。当我更改它并单击提交按钮时,我在模型中得到一个System.NullReferenceException(如源代码中标记的,请向右滚动)。我不明白哪里出了问题以及需要进行哪些更改。

编辑:

当 setter 被注释掉时,异常消失。那么也许是 setter 导致了错误?

解决方案:

使用标准的setter和getter来存储folder_name_shortvalue,但是实现一个公共的get/set方法来设置db中的folder_name并在控制器中调用这个方法。所以:

[NotMapped]
public string folder_name_short { get; set; }
public string getfolder_name_short()
{
    string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
    return shortname;
}
public void setfolder_name_short(string newname)
{
    string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
    folder_name = folder_name.Replace(shortname, newname);
}

【问题讨论】:

  • 您确定 Folder 对象是从数据库中填充的,并且在提交后 folder_name 不为空吗?
  • 是的,folder_name_short 的当前值在输入框中可见。
  • 我的意思是当你提交页面时,就在你来到异常行之前(你可以在该行放置一个断点),看看 folder_name 属性此时它不是 null 吗?
  • 是的,此时folder_name 为空。这导致了我的问题,但我不明白为什么以及需要进行哪些更改。

标签: asp.net-mvc


【解决方案1】:

如果在表单上编辑的值是短名称folder_name_short,那么模型类可以包含其字符串属性:

public string folder_name_short { get; set; }

此属性不包含任何逻辑。包含某些逻辑的任何其他代码都可以在控制器中的操作方法中。

您似乎使用相同的类进行 DB 访问,并作为 MVC 视图的模型类,这是问题的根源。

【讨论】:

  • 我对 asp.net 比较陌生,所以请原谅我提出这个问题,但是您所说的“用于 DB 访问的同一类和作为 MVC 视图的模型类”是什么意思?如果我不在这里实现这个简单的逻辑,那么我必须在每个控制器中都这样做。另请查看我的编辑
  • Folder 装饰有Key 属性,由此我假设您在数据访问层中使用此类,并且还作为Web 应用程序中的视图类,是是这样吗?表单的模型和实体的模型通常是不同的,然后一个统一的类将包含混合数据,具有不同的装饰属性集(数据映射与表单验证)。为视图模型设置一个单独的类会更干净。重复的逻辑可以放在业务类或实用程序(助手)类中。
  • 是的,就是这样。我在视图和数据映射中使用这个类。但它适用于所有其他视图和控制器。我的意思是我可以在所有其他情况下获得folder_name_short,但只有在这个视图中我尝试设置它并在 getter 而不是 setter 上得到错误。我不明白为什么。此外,当我注释掉 setter 时,getter 毫无例外地工作
【解决方案2】:
[HttpPost]
[("Rename")]
public async Task<IHttpActionResult> ChangeFolderPath(Folder folder)
{
    //Put a breakpoint here and make sure the folder has a value
}

可能 setter 方法会覆盖 folder_name 的值。

我会推荐这个帖子来帮助理解自定义设置器 C# properties: how to use custom set property without private field?

编辑

public class Folder
    {
        [Key]
        public string folder_name { get; set; }

        /*Model Logic shouldn't be in the Poco*/
        /*You may put that in your model or best thing would be to implement a repository pattern*/
        public string ShortName()
        {
            string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/")); //System.NullReferenceException here
            return shortname;
        }
        public void SetUsingShortName(string value)
        {
            string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
            this.folder_name = folder_name.Replace(shortname, value);
        }
    }

【讨论】:

  • 你想让我把它添加到我的控制器吗?我连控制器中的Rename Action都没有来,Model中的异常出现在之前
  • 您应该考虑将 folder_name_short 替换为方法而不是属性。我已经更新了我的帖子
  • 当您需要一些逻辑来访问您的 Poco(对象)时,最好的办法是在模型等顶级实体中实现逻辑。因此,您将“数据库实体”与设置获取数据的逻辑分开,这些方法可以在以后在其他地方重用。
猜你喜欢
  • 1970-01-01
  • 2012-09-09
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2021-12-07
  • 2018-11-25
  • 1970-01-01
相关资源
最近更新 更多