edm的需求
公司的EDM软件已经很多年了,需要更新程序并添加一些功能。功能描述:暂时内部使用,要有登陆及权限过滤功能;发送邮件和问卷检测功能。
概述
新需求中程序属于一个流程中的子系统,所以对扩展有要求,登陆时考虑到高并发和容灾,拟采用多进程方式,于是将session记录到数据库里;
发送邮件过程中,由于要发送的邮箱属于10W级,而SMTP服务器限制较多(同一Ip/邮箱,一段时间发送数量上线,发送速度限制,每天部分邮局发送数量上限),对于发送时数据的整理要求较高,还要检测导入的邮箱是否有错误,历史上是否有退订和发送失败中的再次发送不可能成功邮箱的记录,排除不可能成功的邮箱;
问卷需要对导入的文件进行检测是否有多、缺、乱的格式,并生成可访问的链接。
框架搭建
1、框架模型:
原本是想试验一下领域驱动模型来设计,不过最后把自己绕进去了,出不来了,待到有所成的时候再写吧。这里简要的介绍一下:
Models就不用说了,数据库模型;
Commons里面是一些公共类和页面显示数据模型;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 4 namespace Commons.DTO 5 { 6 public class SendTypePages 7 { 8 public int Id { get; set; } 9 public string CustomerName { get; set; } 10 public string EdmName { get; set; } 11 public string Person { get; set; } 12 public string EdmUrl { get; set; } 13 public string DesignUrl { get; set; } 14 public string EmailUrl { get; set; } 15 public string SetTime { get; set; } 16 public string SendStatus { get; set; } 17 } 18 19 public class StopSendType 20 { 21 public int Id { get; set; } 22 public string EdmBeginUrl { get; set; } 23 public string SendStatus { get; set; } 24 public string EdmName { get; set; } 25 } 26 27 public class SendTypeStatis 28 { 29 public string EdmName { get; set; } 30 public string EdmNewUrl { get; set; } 31 public string SetTime { get; set; } 32 public int? TotalCounts { get; set; } 33 public string SendStatus { get; set; } 34 public string CustomerName { get; set; } 35 public double TheBackCount { get; set; } 36 public double TheArriveCount { get; set; } 37 public double TheOpenCount { get; set; } 38 public double EdmBeginUrl { get; set; } 39 public double TheOpenTimesCount { get; set; } 40 public double TheSendCount { get; set; } 41 public double TheTotalCount { get; set; } 42 public double TheUnableCount { get; set; } 43 public string TheArriveProcent { get; set; } 44 public string TheOpenProcent { get; set; } 45 } 46 47 public class TheBackEmailPage 48 { 49 public int Id { get; set; } 50 public string CustomerName { get; set; } 51 public string EdmName { get; set; } 52 public string Email { get; set; } 53 public string Reason { get; set; } 54 public string SetTime { get; set; } 55 } 56 57 public class JsonDate 58 { 59 public int id { get; set; } 60 public string text { get; set; } 61 public List<JsonDate> children { get; set; } 62 } 63 64 public class CustomerList 65 { 66 public int Id { get; set; } 67 public string CustomerName { get; set; } 68 public string Remarks { get; set; } 69 public string Phone { get; set; } 70 public string Email { get; set; } 71 public string Enterprise { get; set; } 72 public string Setion { get; set; } 73 } 74 75 public class QuestionnaireList 76 { 77 public int Id { get; set; } 78 public string CustomerName { get; set; } 79 public string Name { get; set; } 80 public int ReportTimes { get; set; } 81 public int GetBackTimes { get; set; } 82 public string UpTime { get; set; } 83 } 84 85 public class CustomerDto 86 { 87 public int Id { get; set; } 88 public string CustomerName { get; set; } 89 public string Phone { get; set; } 90 public string Email { get; set; } 91 public string Remarks { get; set; } 92 public string Enterprise { get; set; } 93 public string Setion { get; set; } 94 } 95 96 public class SendTest 97 { 98 public int Id { get; set; } 99 public string Email { get; set; } 100 public int IsOpen { get; set; } 101 public int IsReturn { get; set; } 102 public string TheBackReason { get; set; } 103 } 104 105 public class SendTypeEmailDto 106 { 107 public string QqEmail { get; set; } 108 public string WangyiEmail { get; set; } 109 public string TomEmail { get; set; } 110 public string SinaEmail { get; set; } 111 public string SohuEmail { get; set; } 112 public string OtherEmail { get; set; } 113 } 114 }
IRepository里是基础的crud和分页获取数据;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Repository<T> where T : class ,new() 2 { 3 readonly DbContext _entities = EfContextFactory.GetCurrentDbContext(); 4 public void InsertOrUpdate(T entity) 5 { 6 _entities.Set<T>().AddOrUpdate(entity); 7 } 8 9 public void Delete(IEnumerable<T> entity) 10 { 11 foreach (var en in entity) 12 { 13 _entities.Set<T>().Remove(en); 14 } 15 } 16 17 public IEnumerable<T> GetEntity(Func<T, bool> commandText) 18 { 19 var model = _entities.Set<T>().Where(commandText); 20 return model; 21 } 22 23 public IEnumerable<T> GetEntitiesForPaging(int pageNumber, int pageSize, Func<T, object> orderName, Func<T, bool> commandText, out int count) 24 { 25 var model = _entities.Set<T>() 26 .Where(commandText) 27 .OrderBy(orderName).ToList(); 28 var list = model.Skip((pageNumber - 1) * pageSize) 29 .Take(pageSize) 30 .ToList(); 31 count = model.Count; 32 return list; 33 } 34 35 public void Insert(string sql, params object[] paramters) 36 { 37 //entities.Database.SqlQuery<T>( sql, paramters); 38 _entities.Database.ExecuteSqlCommand(sql, paramters); 39 } 40 41 public bool SaveChange() 42 { 43 return _entities.SaveChanges() > 0; 44 } 45 }
Dal则是继承IRepository的方法;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 namespace DAL 2 { 3 public class UserRepository : IRepository.Repository<Models.UserInfo>, IRepository.IRepository<Models.UserInfo> 4 { 5 public List<string> GetEntities(string sql, params object[] paramters) 6 { 7 using (var entities = new Model1Container()) 8 { 9 return entities.Database.SqlQuery<string>(sql, paramters).ToList(); 10 } 11 } 12 } 13 }
Bll将数据库数据进行整理获得前台需要的数据;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //创建发送表 2 public void CreateEmailTable(string sendTableName) 3 { 4 var sql = "CREATE TABLE [dbo].[" + sendTableName + "] " + 5 "([Id] int IDENTITY(1,1) NOT NULL," + 6 "[Email] nvarchar(max) NOT NULL," + 7 "[IsSend] int NULL ," + 8 "[IsArrive] int NULL ," + 9 "[IsOpen] int NULL," + 10 "[IsReturnEmail] int NULL," + 11 "[TheBackReason] nvarchar(128) NULL ," + 12 "[EmailType] nvarchar(128) NULL )"; 13 _sendTypeRepository.Insert(sql); 14 } 15 16 //导入email,通过txt和excel格式 17 public void BulkEmail(string sendTableName, string path) 18 { 19 var sql = "BULK INSERT lxtest2.dbo.LoginTxt " +//要导入的数据库目标表 20 "FROM '" + path + "' " + //文本源数据文件 21 "WITH ( " + 22 "FIELDTERMINATOR = ';', " + //列结束符 23 "ROWTERMINATOR = ' ' " + //行结束符 24 ")"; 25 //SqlParameter[] sqlParameters = 26 //{ 27 // new SqlParameter { ParameterName = "a", Value = 1 }, 28 // new SqlParameter { ParameterName = "b", Value = 2 } 29 //}; 30 31 _sendTypeRepository.Insert(sql); 32 RemoveEmail(sendTableName); 33 34 }