加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何优化此操作以获得更好的性能?我需要把一个计时器放在

发布时间:2020-12-15 05:38:30 所属栏目:百科 来源:网络整理
导读:我有一个我觉得非常沉重的动作结果,所以我想知道如何优化它以便它获得更好的性能.该Web应用程序将同时由100,000个用户使用. 现在我的Actionresult做了以下事情: 从Internet网址中检索XML文件 将xml数据填充到我的数据库 DB数据填充了我的Viewmodel 将模型返
我有一个我觉得非常沉重的动作结果,所以我想知道如何优化它以便它获得更好的性能.该Web应用程序将同时由100,000个用户使用.

现在我的Actionresult做了以下事情:

>从Internet网址中检索XML文件
>将xml数据填充到我的数据库
> DB数据填充了我的Viewmodel
>将模型返回到视图

每次用户访问视图时,此4个函数都会触发.这就是为什么我认为这个Actionresult非常糟糕.

如何将以下内容添加到我的Actionresults中?

添加计时器来检索XML文件并将xml数据填充到DB,就像每10分钟一样,因此每次用户访问视图时都不会触发.每次用户访问站点时,唯一需要触发的功能是viewmodel绑定并返回模型.我怎么能做到这一点?

注意:

> xml文件每10分钟左右更新一次新数据.
>我有大约50个动作结果,它们执行相同的获取xml数据并添加到数据库但有50个不同的xml文件.
>如果xml URL处于脱机状态,则应跳过整个xml检索和数据库添加,然后执行模型绑定

这是我的行动结果:

public ActionResult Index()
        {
            //Get data from xml url (This is the code that shuld not run everytime a user visits the view)
            var url = "http://www.interneturl.com/file.xml";
            XNamespace dcM = "http://search.yahoo.com/mrss/";
            var xdoc = XDocument.Load(url);
            var items = xdoc.Descendants("item")
            .Select(item => new
            {
                Title = item.Element("title").Value,Description = item.Element("description").Value,Link = item.Element("link").Value,PubDate = item.Element("pubDate").Value,MyImage = (string)item.Elements(dcM + "thumbnail")
               .Where(i => i.Attribute("width").Value == "144" && i.Attribute("height").Value == "81")
               .Select(i => i.Attribute("url").Value)
               .SingleOrDefault()
            })
            .ToList();

            //Fill my db entities with the xml data(This is the code that shuld not run everytime a user visits the view)
            foreach (var item in items)
            {
                var date = DateTime.Parse(item.PubDate);
                if (!item.Title.Contains(":") && !(date <= DateTime.Now.AddDays(-1)))
                    {
                        News NewsItem = new News();
                        Category Category = new Category();
                        var CategoryID = 2;

                        var WorldCategoryID = re.GetByCategoryID(CategoryID);
                        NewsItem.Category = WorldCategoryID;

                        NewsItem.Description = item.Description;
                        NewsItem.Title = item.Title.Replace("'","");
                        NewsItem.Image = item.MyImage;

                        NewsItem.Link = item.Link;
                        NewsItem.Date = DateTime.Parse(item.PubDate);
                        re.AddNews(NewsItem);
                        re.save();
                    }
                }


            //All code below this commenting needs to run everytime a user visits the view
            var GetAllItems = re.GetAllWorldNewsByID();

            foreach (var newsitemz in GetAllItems)
            {
                if (newsitemz.Date <= DateTime.Now.AddDays(-1))
                {
                    re.DeleteNews(newsitemz);
                    re.save();
                }

            }

            var model = new ItemViewModel()
            {
               NewsList = new List<NewsViewModel>()
            };

            foreach (var NewsItems in GetAllItems)
            {
                FillProductToModel(model,NewsItems);
            }

            return View(model);
        }

现在,每当用户访问索引视图时,它将获取XML数据并将其添加到数据库中,因此我在存储库中执行的错误修复正在关注addNews:

public void AddNews(News news)
        {
            var exists = db.News.Any(x => x.Title == news.Title);

             if (exists == false)
            {
                db.News.AddObject(news);
            }
            else
            {
                db.News.DeleteObject(news);
            }
        }

任何类型的解决方案和信息都非常感谢!

解决方法

这里可以做很多事情:文件必须是XML(与JSON相比非常冗长)吗?是否必须每次都保存到DB中?

但是,假设您必须执行每个步骤,您就会遇到两个瓶颈:

>等待XML文件下载/解析
>将所有XML数据保存到数据库

有几种方法可以加快速度:

设置轮询间隔

如果您很高兴没有立即看到更新,那么您可以这样做:

>检查DB以获取上次更新.
>如果(且仅当)最后一次更新超过10分钟:

>从Internet网址中检索XML文件
>将xml数据填充到我的数据库

> DB数据填充了我的Viewmodel
>将模型返回到视图

这意味着您的数据可能会过时10分钟,但绝大多数请求只需要填充模型.

根据您使用它的方式,您可以使这更简单 – 只需添加一个OutputCache属性:

[OutputCache(Duration=600)]
public ActionResult Index() { ...

这将告诉浏览器每10分钟刷新一次.您还可以将“位置”属性设置为仅由浏览器或服务器为每个人缓存.

使XML检索异步

在下载XML文件期间,您的代码基本上只是等待加载URL – 在C#中使用新的async关键字,您无需在此等待.

public async Task<ActionResult> Index()
{
    // Get data from xml url
    string url = "http://www.interneturl.com/file.xml";
    XNamespace dcM = "http://search.yahoo.com/mrss/";

    // The await keyword tells the C# code to continue until the slow action completes
    var xdoc = await LoadRemoteXmlAsync(url,dcM);

    // This won't fire until LoadRemoteXmlAsync has finished
    var items = xdoc.Descendants("item")

使用async还有很多东西比我在这里实际涵盖的要多,但是如果你使用最新的C#和MVC,那么开始使用它可能相当简单.

只进行1个DB呼叫

您当前的数据库保存操作非常不理想:

>您的代码通常被称为N+1 problem.
>每次添加时,您首先检查标题并删除记录.这是一种非常缓慢的更新方式,如果很难使用任何索引来优化它.
>您每次都会循环浏览所有新闻文章,并逐一删除所有旧文章.这比新闻中的单个删除慢得多……查询.

基于此,我尝试以下更改(按照粗略的顺序,它们应该是多么容易):

>更改AddNews方法 – 如果新数据不是新的,则不保存该项的任何更改.
>将删除循环更改为新闻中的单个删除,其中Date< = @yesterday
>查看新闻项目标题和日期的索引,这些索引似乎是您查询最多的字段.
>查看使用执行upsert / merge的操作替换AddNews方法
> re.GetByCategoryID会命中你的数据库吗?如果是这样,请考虑将其拆分并将其构建到更新查询中或填充字典以更快地查找它.

基本上,每个新的新闻文章应该(最多)1个DB操作,并且1个DB操作要删除旧的.你现在有不到一天的每篇文章3(re.GetByCategoryID db.News.Any db.News.Add | DeleteObject)另外1(re.GetAllWorldNewsByID),然后每篇文章还要删除1(re.DeleteNews).

添加分析

您可以向MVC项目添加概要分析,它将告诉您每个步骤的确切时间,并帮助找到如何使用MiniProfiler优化它们.它在StackOverflow上使用,我自己也经常使用它 – 它会告诉您哪些步骤正在减速你失败了,哪些不值得微观优化.

如果您不想使用Visual Studio中的优化工具以及RedGate ANTS等第三方工具.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读