samesite


【步步为营 Entity Framework+Reporting service开发】-(3) 创建commandline 应用程序 ,使用EF导入数据

接上一章,我们要创建一个commandline 应用程序,通过输入参数,可以让它去指定目录读取文件,并且导入数据库

【设计】

在编写这个程序之前,我们要想想这个程序都需要做什么?

1.读取commandline 参数。一个目录,taskid 和taskName 3个参数。

2.到指定目录读取csv/txt 文件,把csv/txt 转成 DataTable (这里有两种txt文件,trend 和bar)

3.去数据库中查询,如果当前taskid 没有记录则插入记录。否则更新记录。

 

根据上边需要,我们需要创建如下类/方法:

 

 

 

 

 

 

点击解决方案->Add new project->Console Application

命名为:ReportingSyncer。

proj 右键属性,修改命名空间和程序集名称,与前边ReportingDBManager的前缀保持一致,即:CnBlogsDemos.ReportingSyncer

创建commandline 类:

View Code
namespace CnBlogsDemos.ReportingSyncer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;


    public class CommandLine
    {
        protected Dictionary<string, string> _command;
        protected string _defaultConfig;

        public string InputDir
        {
            get
            {
                if (_command.ContainsKey("input"))
                {
                    return _command["input"];
                }
                throw new Exception("The expected parameter /input:[directory] is missing!");
            }
        }

        public string ConfigFilePath
        {
            get
            {
                if (_command.Keys.Contains("config"))
                {
                    return _command["config"];
                }
                return _defaultConfig;
            }
        }

        public string TaskID
        {
            get
            {
                if (_command.ContainsKey("taskid"))
                {
                    return _command["taskid"];
                }
                throw new Exception("The expected parameter /taskid:[id] is missing!");
            }

        }

        public string TaskName
        {
            get
            {
                if (_command.ContainsKey("taskname"))
                {
                    return _command["taskname"];
                }
                throw new Exception("The expected parameter /taskname:[name] is missing!");
            }

        }

        public CommandLine(string[] args)
        {
            ParseCommandLine(args);
            CheckMandatoryParameter();
        }

        public virtual string PrintInputParameters()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Input Parameter:");
            foreach (KeyValuePair<string, string> param in _command)
            {
                sb.Append(string.Format("/{0}:{1}\t", param.Key, param.Value));
            }
            return sb.ToString();
        }

        private void ParseCommandLine(string[] args)
        {
            if (0 == args.Length ||
                (1 == args.Length &&
                (args[0].Contains("?") || args[0].ToLower().Contains("help"))))
            {
                Prompt();
                throw new ArgumentException("");
            }

            _command = new Dictionary<string, string>();
            try
            {
                foreach (string arg in args)
                {
                    string[] param = arg.ToLower().Split(new char[] { ':' }, 2);
                    _command.Add(param[0].Replace("/", ""), param[1]);
                }
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message);
            }
        }

        protected virtual void CheckMandatoryParameter()
        {
            throw new NotImplementedException();
        }

        protected virtual void Prompt()
        {
            throw new NotImplementedException();
        }
    }
}

 

创建DataSyncer类(主要的操作都在这),先空着。

修改Programs类:

using System;
using CnBlogsDemos.ReportingSyncer;

namespace ReportingSyncer
{
    class Program
    {
        static int Main(string[] args)
        {
            int iRet = -1;
            try
            {
                CommandLine cmd = new CommandLine(args);
                DataSyncer ds = new DataSyncer(cmd);
            }
            catch (Exception e)
            {
                //TODO
            }
            return iRet;
        }
    }
}

现在我们开始写DataSyncer类了。

首先添加EF引用。由于刚才我们在上一个proj 引用过了。我们可以去c:\users\你的名字\documents\visual studio 2010\Projects\ReportingSyncer\packages\EntityFramework.4.3.1\lib\net40\EntityFramework.dll找。我的是64位机器。32位的话,应该忽略(X86)。

再添加项目引用-》ReportingDBManager,这样我们才可以使用刚才的DbStoreContext类。

 

根据上边类图所示:

DataSyncer类如下,具体的地方可以看代码注释:

namespace CnBlogsDemos.ReportingSyncer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Data;
    using CnBlogsDemos.ReportingDBManager;


    public class DataSyncer
    {
        private CommandLine _cmd;

        public DataSyncer(CommandLine cmd)
        {
            // TODO: Complete member initialization
            this._cmd = cmd;
        }

        internal int RunInCommandLineMode()
        {
            int iRet = -1;
            int taskId = 0;
            string inputDir = _cmd.InputDir;
            string taskName = string.Empty;
            string type = string.Empty;

            //Get taskid
            int.TryParse(_cmd.TaskID, out taskId);
            // if after parsing ,task id still equals 0 ,return
            if (taskId.Equals(0))
            {
                Console.WriteLine("taskid is invalid");
                return -1;
            }
            // if input directory is not exist parsing return
            if (!Directory.Exists(inputDir))
            {
                Console.WriteLine("input directory is not exist");
                return -1;
            }
            else
            {
                //read files from input dir
                var files = Directory.GetFiles(inputDir);

                if (!files.Any())
                {
                    Console.WriteLine("there is not files under input directory");
                    return -1;
                }
                else
                {
                    foreach (var file in files)
                    {
                        if (file.Contains("trend.txt"))
                        {
                            type = "trend";
                            InsertAnalysisData(file, taskId, taskName, type);
                        }
                        else if (file.Contains("bar.txt"))
                        {
                            type = "bar";
                            InsertAnalysisData(file, taskId, taskName, type);
                        }
                    }
                }


            }



            return iRet;

        }

        public void InsertAnalysisData(string filePath, int taskId, string taskName, string type)
        {
            if (File.Exists(filePath))
            {

                if (type.Equals("bar", StringComparison.OrdinalIgnoreCase))
                {
                    var dataRows = this.GetTableFromCSV(filePath).AsEnumerable();
                    // 创建一个新的 dbstore context 实例
                    using (DbStoreContext dsc = new DbStoreContext())
                    {
                        // 如果 Bars表 存在任何相同的TaskID,删除相关记录
                        if (dsc.Bars.Any(n => n.TaskID.Equals(taskId)))
                        {
                            foreach (var item in dsc.Bars.Where(n => n.TaskID.Equals(taskId)))
                            {
                                dsc.Bars.Remove(item);
                            }
                        }
                        
                        foreach (var row in dataRows)
                        {
                            // 注意 ,这个 row.Field<string>(index);中的index 对应我们csv/txt 文件中的数据列,索引从0开始
                            Bar b = new Bar();
                            b.KeyWord = row.Field<string>(0);
                            b.B1Better = Convert.ToInt32(row.Field<string>(1));
                            b.Equal = Convert.ToInt32(row.Field<string>(2));
                            b.B2Better = Convert.ToInt32(row.Field<string>(3));
                            b.Winner = row.Field<string>(4);
                            b.IsActive = true;
                            b.type = type;
                            b.TaskID = taskId;
                            b.TaskName = taskName;
                            dsc.Bars.Add(b);
                        }
                        //保存修改。EF会去执行插入数据到DB,默认开启事务
                        dsc.SaveChanges();
                    }
                }
                else if (type.Equals("trend", StringComparison.OrdinalIgnoreCase))
                {
                    var tailWholePageTrendDataRows = this.GetTableFromCSV(filePath).AsEnumerable();
                    using (DbStoreContext dsc = new DbStoreContext())
                    {
                        if (dsc.Trends.Any(n => n.TaskID.Equals(taskId)))
                        {
                            foreach (var item in dsc.Trends.Where(n => n.TaskID.Equals(taskId)))
                            {
                                dsc.Trends.Remove(item);
                            }
                        }
                        foreach (var row in tailWholePageTrendDataRows)
                        {
                            // 注意 ,这个 row.Field<string>(index);中的index 对应我们csv/txt 文件中的数据列,索引从0开始
                            Trend t = new Trend();
                            t.id = Convert.ToInt32(row.Field<string>(0));
                            t.TaskID = taskId;
                            t.Time = Convert.ToDateTime(row.Field<string>(3));
                            t.B1Better = Convert.ToInt32(row.Field<string>(4));
                            t.Equal = Convert.ToInt32(row.Field<string>(5));
                            t.B2Better = Convert.ToInt32(row.Field<string>(6));
                            t.UnCertain = Convert.ToInt32(row.Field<string>(7));
                            t.GrandTotal = Convert.ToInt32(row.Field<string>(8));
                            t.TaskName = taskName;
                            t.IsActive = true;
                            t.type = type;
                            dsc.Trends.Add(t);
                        }
                        dsc.SaveChanges();
                    }

                }

            }
        }

        /// <summary>
        /// GetTableFromCSV file
        /// </summary>
        /// <param name="csvFilePath">file path</param>
        /// <returns>data table</returns>
        private  DataTable GetTableFromCSV(string csvFilePath)
        {
            using (StreamReader sr = new StreamReader(csvFilePath))
            {
                string line = sr.ReadLine();
                if (!string.IsNullOrEmpty(line))
                {
                    string[] columns = line.Split('\t');
                    DataTable dt = new DataTable();
                    foreach (string columnName in columns)
                    {
                        dt.Columns.Add(columnName);
                    }

                    while ((line = sr.ReadLine()) != null)
                    {
                        DataRow dr = dt.NewRow();
                        string[] dataColumns = line.Split('\t');
                        dt.Rows.Add(dataColumns);
                    }
                    return dt;
                }
                throw new Exception(string.Format("File Content in {0} is empty", csvFilePath));
            }
        }
    }
}

 

倒数第二步:创建app.config。上篇文章说过。我们删除了ReportingDBManager类库中的app.config。

我们要在ReportingSyncer 类库中添加一个app.config指定我们的连接字符串

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ReportingDataBase"
connectionString="Initial Catalog=DemoReportDB;data source=.;Integrated Security=SSPI;Trusted_Connection=Yes" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>

 

 

 

 

最后一步,创建测试数据。

让我们创建一个文件夹E:\demos\reportingImprot。下边包含2个txt文件:trend.txt 和 bar.txt

trend.txt:

id taskid taskname time b1 equal b2 uncertain grandtotal 0 1 task1 2012-6-27 200 300 280 220 1000

注意中间是tab分割。

bar.txt:

KeyWord B1Better Equal B2Better Winner 联众 2 0 3 B1 疯狂倒计时 0 0 3 B2 张娜拉 0 1 2 B1 截图软件 1 0 1 B2

 

因为有汉字,请保存为unicode格式

为了方便模拟用户输入,我们可以预设commandline 参数:

右击ReportingSyncer 项目属性:debug-》Commandline arguments 输入:/input:E:\demos\reportingImprot/taskid:5 /taskname:TestTask。

在实际使用时候可以用cmd找到你的bin目录 执行release /debug 下的 exe文件。

例如 cmd-> c:

           ->cd e:\C:\Users\ricky\Documents\Visual Studio 2010\Projects\ReportingSyncer\ReportingSyncer\bin\Release reportingsyncer /input:E:\demos\reportingImprot/taskid:5 /taskname:TestTask

我们还是在debug 下试试吧。运行,也可以调试看看。

检查本地数据库。太神奇了吧?数据已经导进来了。

 

检查一下表结构

 

好,这章就讲到这里。

下一章会继续介绍如何使用vs 创建report

 

源代码下载

posted @ 2012-07-05 10:17  技术弟弟  阅读(2109)  评论(7编辑  收藏  举报