every night i have a trigger that executes asp.net page with method that first retrieves from DB users with needed details and then emails them with information they need like ie. users that does not have an image in their profile. Once i get data from DB i build large string with encoded HTML and assign it to MailMessage.Body tag. There are about 20000 users per action/night who get the mail. Stored procedures just get users based on criteria i need nothing to optimize there (after proper indexes been made).
How do i optimize it? Can i create sort of queue in ASP.NET that it will be executed all day long without one time action? Maybe i can use async actions to send few emails per time.
Need advice, if you have question about how i perform each action in order to help me don’t be afraid to ask, i will answer i just don’t know what place in code may interest you.
protected void Page_Load(object sender, EventArgs e)
{
string type = Request.QueryString["type"];
string spName = "";
string message = "";
switch (type)
{
//getUsersWithoutPictures
case "uwp":
spName = "getUsersWithoutPictures";
message = getUsersWithoutPicturesTemplate();
break;
//getUsersWithoutText
case "uwt":
spName = "getUsersWithoutText";
message = getUsersWithoutTextTemplate();
break;
//getUsersWithoutEnteringWebsiteForTwoWeeks
case "uwewftw":
spName = "getUsersWithoutEnteringWebsiteForTwoWeeks";
message = getUsersWithoutEnteringWebsiteForTwoWeeksTemplate();
break;
//getUsersWithoutHobbies
case "uwh":
spName = "getUsersWithoutHobbies";
message = getUsersWithoutHobbiesTemplate();
break;
//getUsersWithoutCharateristics
case "uwc":
spName = "getUsersWithoutCharateristics";
message = getUsersWithoutCharateristicsTemplate();
break;
//getUsersWithoutActivation
case "uwa":
spName = "getUsersWithoutActivation";
message = getUsersWithoutActivationTemplate();
break;
default:
Response.Write("failure");
Response.End();
break;
}
DataTable recipientsList = new DataTable();
using (SqlConnection cn = cms.connect("someconnectionstring"))
{
SqlDataAdapter adp = new SqlDataAdapter(spName, cn);
adp.SelectCommand.CommandType = CommandType.StoredProcedure;
adp.Fill(recipientsList);
}
foreach (DataRow row in recipientsList.Rows)
{
try
{
IPHostEntry emailHost = Dns.GetHostEntry(row["email"].ToString().Remove(0, row["email"].ToString().LastIndexOf("@") + 1));
MailMessage myMessage = new MailMessage(new MailAddress("support@" + row["registratioSite"].ToString()), new MailAddress(row["email"].ToString()));
myMessage.Subject = "";
myMessage.Body = getGenericEmailTemplate(AffDomains.getFullDomain(row["registratioSite"].ToString()), message, row["email"].ToString(), row["usernumber"].ToString(), row["nick"].ToString());
myMessage.IsBodyHtml = true;
SmtpClient mySmtp = new SmtpClient("mysmtp.server.com");
mySmtp.Send(myMessage);
}
catch (Exception)
{
}
}
Response.Write("success");
Response.End();
}
private string getGenericEmailTemplate(string domain, string message, string email, string usernumber, string nick)
{
return "some html";
}
private string getUsersWithoutPicturesTemplate()
{
return "some message";
}
private string getUsersWithoutTextTemplate()
{
return "some message 2";
}
private string getUsersWithoutEnteringWebsiteForTwoWeeksTemplate()
{
return "some message 3";
}
private string getUsersWithoutHobbiesTemplate()
{
return "some message 4";
}
private string getUsersWithoutCharateristicsTemplate()
{
return "some message 5";
}
private string getUsersWithoutActivationTemplate()
{
return "some message 6";
}
Some pointers based on your current implementation:
If you want this solution to scale way beyond its current limits however, you might want to think about some sort of multithreaded (or distrubuted) producer/consumer queue. I won’t elaborate further here – there are plenty of examples on the web.