如何在.NET Core中创建没有数据库的集合

时间:2019-07-15 08:51:23

标签: c# .net asp.net-core

如何将项目添加到列表SearchedVideos中? 我希望将这些项目保留在列表中,直到申请结束。 现在我有这样的错误:

  

NullReferenceException:对象引用未设置为对象的实例。

我用道具作为 Singleton 创建上下文

public List<QueryViewModel> SearchedVideos { get; set; }

启动

services.AddSingleton<YtContext>();

我的模型

public class ExecutedQuery
{
    public Query Query { get; }
    public string Title { get; set; }
    public IReadOnlyList<Video> Videos { get; set; }

    public ExecutedQuery(Query query, string title, IReadOnlyList<Video> videos)
    {
        Query = query;
        Title = title;
        Videos = videos;
    }
}

我的服务

public async Task<ExecutedQuery> ExecuteQueryAsync(Query query)
    {
        // Search
        if (query.Type == QueryType.Search)
        {
            var videos = await _youtubeClient.SearchVideosAsync(query.Value);
            var title = $"Search: {query.Value}";

            var executedQueries = new ExecutedQuery(query, title, videos);

            var qw = new QueryViewModel
            {
                ExecutedQueries = executedQueries,
            };

            _ytcontext.SearchedVideos.Add(qw);

            return executedQueries;
        }
    }

我的 QueryViewModel

public ExecutedQuery ExecutedQueries { get; set; }

我的控制器

[HttpGet("Search/all")]
    public async Task<IActionResult> ListAllQueriesAsync(string query)
    {
        var req = _queryService.ParseQuery(query);
        var res = await _queryService.ExecuteQueryAsync(req);

        return View(res);
    }

3 个答案:

答案 0 :(得分:0)

如果要将此列表从一个实例编辑到另一个实例,则需要使用某种数据源。如果没有数据库选项,则必须使用文本文件。使用Json字符串并序列化/反序列化到您的对象。 https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-serialize-and-deserialize-json-data。我已经使用这种方法来模拟应用程序,但是如果您要对文件进行大量写入,则可能会遇到问题。

如果您可以在应用程序中对列表进行硬编码,则可以使用Singleton。在这里阅读。 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2

答案 1 :(得分:0)

每个请求都是它自己的事情,不受之前或之后发生的任何事情的影响。因此,您几乎是从空白开始。在一个或多个其他请求之间保持状态的典型方法是会话。会话本质上是假状态,通过服务器端(一些持久性存储)和客户端组件(cookie)的组合,可以实现状态持久性。但是,尤其是在服务器端,您仍然需要某种类型的存储,通常是某种类型的数据库,无论是关系型(SQL Server等)还是NoSQL(Redis等)。默认的会话存储将在内存中,这可能满足您的需求,但是由于内存易变,因此任何类型的应用程序重新启动都会将存储在其中的所有内容都存储在其中。

或者,存在具有单例寿命的静态对象和对象。无论哪种情况,它们实际上都与内存中的存储相同-它们将保持应用程序的生命周期,而不再存在。

统计信息只是带有关键字static的成员。这可能是最简单,最直接的方法,但也是最脆弱的方法。测试静态几乎是不可能的,因此您基本上是在代码中创建任何可能发生的黑洞。

更好的方法是简单地使用具有单身寿命的对象。这些可以通过服务集合上的AddSingleton<T>方法创建。例如,您可以创建一个像这样的类:

public class MySingleton
{
    public ICollection<IReadOnlyList<Video>> SearchedVideo { get; set; }
}

然后将其注册为ConfigureServices中的单例:

services.AddSingleton<MySingleton>();

然后,在控制器中的视图等中,您可以注入MySingleton来访问SearchedVideos属性。作为一个单例,在那里的数据将在应用程序的生命周期中持续存在。

会话(尤其是内存会话)与静态或单例之间的主要区别是广度之一。会话将始终绑定到特定的客户端,而静态变量和单例对象的范围将取决于应用程序。这意味着,如果您使用静态变量或单例, all 客户端将看到相同的数据,并有可能操纵相同的数据。如果您需要特定于客户端的内容,则必须使用会话。

答案 2 :(得分:0)

@natsukiss我猜您正在尝试从空属性调用 Add()方法。即使您创建列表,也应该为 SearchedVideo 属性设置初始实例。因为如果不创建实例,则意味着该属性在内存中将没有地址。因此,有时我们使用 string TestVal =“” 。这意味着我们在公共语言运行时(CLR)上设置初始值,以在内存中找到地址。

public List<QueryViewModel> SearchedVideos { get; set; } = new List<QueryViewModel>(); //<==

或者如果您正在使用EntityFramework,则应该使用

public ICollection<QueryViewModel> SearchedVideos { get; set; } = new HashSet<QueryViewModel>(); //<===