Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc WCF服务生成Excel文件(10000行)并将其发送给客户端(性能问题)_Asp.net Mvc_Wcf_Serialization - Fatal编程技术网

Asp.net mvc WCF服务生成Excel文件(10000行)并将其发送给客户端(性能问题)

Asp.net mvc WCF服务生成Excel文件(10000行)并将其发送给客户端(性能问题),asp.net-mvc,wcf,serialization,Asp.net Mvc,Wcf,Serialization,在Asp.net MVC应用程序中,我们有一个页面可以下载动态生成的excel报告。客户端应用程序调用WCF服务,该服务生成excel文件并将文件名返回给客户端。WCF服务使用OpenXMLSAX方法生成excel文件 服务器调用存储过程并使用数据读取器获取数据。通常该文件包含10000条记录。我们在测试环境中没有遇到任何性能问题。在生产中,如果有10人访问报告,服务器内存将达到最大值,cpu利用率也将达到98%。因此,它会给该服务器中的所有应用程序带来问题。服务器只有4GB RAM。我正在运行

在Asp.net MVC应用程序中,我们有一个页面可以下载动态生成的excel报告。客户端应用程序调用WCF服务,该服务生成excel文件并将文件名返回给客户端。WCF服务使用OpenXMLSAX方法生成excel文件

服务器调用存储过程并使用数据读取器获取数据。通常该文件包含10000条记录。我们在测试环境中没有遇到任何性能问题。在生产中,如果有10人访问报告,服务器内存将达到最大值,cpu利用率也将达到98%。因此,它会给该服务器中的所有应用程序带来问题。服务器只有4GB RAM。我正在运行4应用程序。通常我的应用程序占用更多内存

代码如下:

public string GetMemberRosterHistoryFile(string VendorId, string versionId, DateTime FromDate, string ActionIndicator)
{
    string path = ConfigurationManager.AppSettings["FilePath"] + Guid.NewGuid() + ".xlsx";
    try
    {
        path = PathInfo.GetPath(path);
        log4net.ThreadContext.Properties["MethodName"] = "GetMemberRostersHistory";
        log.Info("Getting member rosters History");
        string sConn = ConfigurationManager.ConnectionStrings["VendorConnectContext"].ConnectionString;
        using (SqlConnection oConn = new SqlConnection(sConn))
        {
            oConn.Open();
            log.Debug("Connected");
            string sCmd = "pGetMemberRostersHistory";
            SqlCommand oCmd = new SqlCommand(sCmd, oConn);
            oCmd.CommandTimeout = Int32.MaxValue;
            oCmd.CommandType=CommandType.StoredProcedure;
            oCmd.Parameters.AddWithValue("@FromDate", FromDate.ToShortDateString());
            oCmd.Parameters.AddWithValue("@ActionIndicator", ActionIndicator);
            int index=1;
            StringBuilder programs = new StringBuilder();
            if (string.IsNullOrEmpty(versionId))
            {
                foreach (string value in GetPrograms(VendorId))
                {
                    if (index > 1)
                    {
                        programs.Append(",");
                    }
                    programs.Append(value);
                    index++;
                }
            }
            else
            {
                foreach (string value in GetPrograms(VendorId, versionId))
                {
                    if (index > 1)
                    {
                        programs.Append(",");
                    }
                    programs.Append(value);
                    index++;
                }
            }
            oCmd.Parameters.AddWithValue("@ProgramsList", programs.ToString());

            string[] FieldNames = new string[] 
                {
                        "ActionIndicator", 
                    "ChangeNotes",
                    "ActionEffectiveDate",
                    "MembershipTerminationDate",
                    "GPOId",
                    "GLN",
                    "HIN",
                    "Name1",
                    "Name2",
                    "AddressType",
                    "Address1",
                    "Address2",
                    "Address3",
                    "City",
                    "StateProvince",
                    "ZipPostalCode",
                    "Country",
                    "PhoneNbr",
                    "FaxNbr",
                    "RelationshipToGPO",
                    "RelationshipToDirectParent",
                    "DirectParentGPOId",
                    "DirectParentName1",
                    "TopParentGPOId",
                    "TopParentName1",
                    "MemberStatus",
                    "MembershipStartDate",
                    "OrganizationalStatus",
                    "ClassOfTradeName",
                    "DEA",
                    "DSHorHRSA",
                    "PHEffectiveDate",
                    "PHExpirationDate",
                    "BLPHEffectiveDate",
                    "BLPHExpirationDate",
                    "MMEffectiveDate",
                    "MMExpirationDate",
                    "BLMMEffectiveDate",
                    "BLMMExpirationDate",
                    "DIEffectiveDate",
                    "DIExpirationDate",
                    "LBEffectiveDate",
                    "LBExpirationDate",
                    "NMEffectiveDate",
                    "NMExpirationDate"
                    ,"BLMemberId"
                        ,"GPOCorporateGroup"
                        ,"GPOAffiliateGroup"
                        ,"GPO2AffiliateGroup"
                        ,"GPORelatedGroup"
                        ,"GPOIDNGroup"

                };
        string[] columnNames = new string[] 
                    {
                        "Action Indicator",
                        "Change Notes",
                        "Action Effective Date",
                        "Membership Termination Date",
                            "GPO ID",
                            "GLN",
                            "Health Industry Number (HIN)",
                            "Name 1",
                            "Name 2",
                            "Address Type",
                            "Address 1",
                            "Address 2",
                            "Address 3",
                            "City",
                            "State/Province",
                            "Postal Code",
                            "Country",
                            "Phone",
                            "Fax",
                            "Relationship to GPO",
                            "Relationship to Direct Parent",
                            "Direct Parent GPO ID",
                            "Direct Parent Name 1",
                            "Top Parent GPO ID",
                            "Top Parent Name 1",
                            "Member Status",
                            "Membership Start Date",
                            "Organizational Status",
                            "Class of Trade",
                            "DEA #",
                            "DSH and/or HRSA Number",
                            "Pharmacy Start Date",
                            "Pharmacy End Date",
                            "BL Pharmacy Start Date",
                            "BL Pharmacy End Date",
                            "Med Surg Start Date",
                            "Med Surg End Date",
                            "BL Med Surg Start Date",
                            "BL Med Surg End Date",
                            "Food Service Start Date",
                            "Food Service End Date",
                            "Laboratory Start Date",
                            "Laboratory End Date",
                            "NonMedical Start Date",
                            "NonMedical End Date"
                            ,"Broadlane ID"
                            ,"Corporate Group"
                            ,"Affiliate Group"
                            ,"2nd Affiliate Group"
                            ,"Related Group"
                        ,"IDN Group"
                    };
            //object result = oCmd.ExecuteScalar();
            //int count=(result!=null ? (int)result : 0);
            //oCmd.CommandText = "pGetMemberRostersHistory";
            //oCmd.CommandTimeout = Int32.MaxValue;
            using (SqlDataReader oReader = oCmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                SAXExcelExporter exporter = new SAXExcelExporter();
                exporter.Export(oReader, columnNames, FieldNames, path, "MemberRoster");

            }
        }
        return path;
    }
    catch (Exception ex)
    {
        log.Error("In exception", ex);
        return null;
    }
}
出口代码:

public void Export(SqlDataReader export, string[] columnNames, string[] fieldNames, string filename, string sheetName)
{
    Assembly _assembly = Assembly.GetExecutingAssembly();
    Stream stream = _assembly.GetManifestResourceStream("MA.VMS.Server.Template.xlsx");
    FileStream newfile = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite);
    stream.CopyTo(newfile);
    stream.Close();
    newfile.Close();
    using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(filename, true))
    {
        WorkbookPart workbookPart = myDoc.WorkbookPart;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.Last();
        string origninalSheetId = workbookPart.GetIdOfPart(worksheetPart);

        WorksheetPart replacementPart = workbookPart.AddNewPart<WorksheetPart>();
        string replacementPartId = workbookPart.GetIdOfPart(replacementPart);

        OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
        OpenXmlWriter writer = OpenXmlWriter.Create(replacementPart);

        while (reader.Read())
        {
            if (reader.ElementType == typeof(SheetData))
            {
                if (reader.IsEndElement)
                    continue;
                writer.WriteStartElement(new SheetData());
    Row hr = new Row();
                writer.WriteStartElement(hr);

                for (int col = 0; col < columnNames.Length; col++)
                {
                    Cell c = new Cell();
                    c.DataType = CellValues.InlineString;
                    InlineString iss = new InlineString();
                    iss.AppendChild(new Text() { Text = columnNames[col] });
                    c.AppendChild(iss);
                    writer.WriteElement(c);
                }
    writer.WriteEndElement();

                //for (int row = -1; row < count; row++)
                while (export.Read())
                {

                    Row r = new Row();
                    writer.WriteStartElement(r);
                    //if (row == -1)
                    //{
                    //    for (int col = 0; col < columnNames.Length; col++)
                    //    {
                    //        Cell c = new Cell();
                    //        c.DataType = CellValues.InlineString;
                    //        InlineString iss = new InlineString();
                    //        iss.AppendChild(new Text() { Text = columnNames[col] });
                    //        c.AppendChild(iss);
                    //        writer.WriteElement(c);
                    //    }
                    //}
                    //else
                    //{
                        //export.Read();
                        for (int col = 0; col < fieldNames.Length; col++)
                        {
                            Cell c = new Cell();
                            c.DataType = CellValues.InlineString;
                            InlineString iss = new InlineString();
                            iss.AppendChild(new Text() { Text = GetValue(export[fieldNames[col]]) });

                            c.AppendChild(iss);
                            writer.WriteElement(c);
                        }
                    //}
                    writer.WriteEndElement();

                }

                writer.WriteEndElement();
            }
            else
            {
                if (reader.IsStartElement)
                {
                    writer.WriteStartElement(reader);
                }
                else if (reader.IsEndElement)
                {
                    writer.WriteEndElement();
                }
            }
        }

        reader.Close();
        writer.Close();

        Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Id.Value.Equals(origninalSheetId)).First();
        sheet.Id.Value = replacementPartId;
        workbookPart.DeletePart(worksheetPart);

    }
}
public void导出(SqlDataReader导出,string[]列名,string[]字段名,string文件名,string sheetName)
{
Assembly _Assembly=Assembly.getExecutionGassembly();
Stream=_assembly.GetManifestResourceStream(“MA.VMS.Server.Template.xlsx”);
FileStream newfile=newfilestream(文件名,FileMode.Create,FileAccess.ReadWrite);
stream.CopyTo(newfile);
stream.Close();
newfile.Close();
使用(SpreadsheetDocument myDoc=SpreadsheetDocument.Open(文件名,true))
{
WorkbookPart WorkbookPart=myDoc.WorkbookPart;
WorksheetPart WorksheetPart=workbookPart.WorksheetParts.Last();
string origninalSheetId=workbookPart.GetIdOfPart(工作表部分);
WorksheetPart replacementPart=workbookPart.AddNewPart();
字符串replacementPartId=workbookPart.GetIdOfPart(replacementPart);
OpenXmlReader=OpenXmlReader.Create(工作表部分);
OpenXmlWriter=OpenXmlWriter.Create(replacementPart);
while(reader.Read())
{
if(reader.ElementType==typeof(SheetData))
{
if(reader.IsEndElement)
继续;
writer.writeStarElement(新的SheetData());
行hr=新行();
writer.writeStarteElement(hr);
for(int col=0;cols.Id.Value.Equals(originalSheetId)).First();
sheet.Id.Value=replacementPartId;
workbookPart.DeletePart(工作表部分);
}
}
我很担心。当我查看proc时,它会在26秒内返回数据,而excel下载需要3分钟以上

对于这种情况,我应该怎么做? 以下是我正在思考的解决方案:

  • 将excel下载异步移动并发送要下载的链接
  • 在不同的服务器上部署这两个应用程序
  • 在服务器上执行内存探查器

  • 这些都是好主意。但是,我将更深入地研究性能调优

    你说你有4GB的内存。假设1GB的开销都被消耗掉了,服务器上的其他应用程序都处于空闲状态。因此,剩下3GB的空间可以处理10份报告。每台300MB。你的报告差不多那么大吗?假设您的输出是100MB,那么您将很容易地获得300MB,并使用各种内部表示,您应该删除这些表示。但是,如果您只生成10MB,那么您需要解决一些严重的性能问题

    你说这已经在生产了。因此,一个快速的创可贴解决方案就是让这个应用程序拥有大量的RAM。这应该会为你赢得一点时间,让你找到它占用如此多内存的原因

    长久
    List<OpenXmlAttribute> oxa;
    for (int col = 0; col < fieldNames.Length; col++)
    {
        oxa = new List<OpenXmlAttribute>();
        // this is the data type ("t"), with CellValues.String ("str")
        oxa.Add(new OpenXmlAttribute("t", null, "str"));
    
        // it's suggested you also have the cell reference, but
        // you'll have to calculate the correct cell reference yourself.
        // Here's an example:
        //oxa.Add(new OpenXmlAttribute("r", null, "A1"));
    
        writer.WriteStartElement(new Cell(), oxa);
    
        writer.WriteElement(new CellValue(GetValue(export[fieldNames[col]])));
    
        // this is for Cell
        writer.WriteEndElement();
    }
    
    <GetMemberRosterHistoryFile>
        <MethodParameters>
            <String>
                &lt;WordDocXml&gt;
                    &lt;SomeXmlElement someAttribute=&quot;foo&quot; /&gt;
                &lt;/WordDoxXml&gt;
            </String>
        </MethodParameters>
    </GetMemberRosterHistoryFile>