Fork me on GitHub
Lazy Row Mapping

前言

在做架构设计的时候,数据对象进出系统边界,可以采用先前的文章介绍的[Architecture Pattern] Repository,来将外部的系统、模块、数据库…等等,隔离在架构之外。而当系统采用关系数据库来做为储存数据库的时候,开发人员必需要在程序内加入ORM(Object Relational Mapping)的功能,才能将数据对象与关系数据库数据做互相的转换。

 

但当开发人员要从数据库查询大量数据的时候,会惊觉上述ORM的运作模式是:将数据库查询到的「所有数据」,转换为数据对象集合放在「内存内」,再交由系统去使用。「所有数据」、「内存内」这两个关键词,决定了在大量数据的处理上,这个运作模式有风险。毕竟就算计算机内存的售价再便宜,使用者大多还是不会为了软件,多投资金钱去购买内存。

 

本篇文章介绍一个「Lazy Row Mapping」实做,用来处理对关系数据库查询大量数据做ORM的需求。为自己做个纪录,也希望能帮助到有需要的开发人员。

 

使用

因为实做的内容有点硬,所以先展示使用范例,看能不能减少开发人员按上一页离开的机率…。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
 
namespace LazyRowMappingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // UserRepositoryProvider
            UserRepositoryProvider userRepositoryProvider = new UserRepositoryProvider();
 
            // QueryAll
            foreach (User user in userRepositoryProvider.QueryAll())
            {               
                Console.WriteLine("Name : " + user.Name);
                Console.WriteLine("Create Time : " + user.CreateTime);
                Console.WriteLine("Read Time : " + DateTime.Now);
                Console.WriteLine();
                System.Threading.Thread.Sleep(2000);
            }
 
            // End
            Console.ReadLine();
        }
    }
 
    public class User
    {
        // Properties
        public string Name { get; set; }
 
        public DateTime CreateTime { get; set; }
    }
 
    public class UserRepositoryProvider
    {
        // Methods
        public IEnumerable<User> QueryAll()
        {
            // Arguments
            string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\LazyRowMappingSample.mdf;Integrated Security=True;User Instance=True";
 
            string commandText = @"SELECT * FROM [User]";
 
            SqlParameter[] parameters = new SqlParameter[] { };
 
            Func<IDataRecord, User> rowMappingDelegate = delegate(IDataRecord dataRecord)
            {
                User user = new User();
                user.Name = Convert.ToString(dataRecord["Name"]);
                user.CreateTime = DateTime.Now;
                return user;
            };
 
            // Return
            return new SqlLazyRowMappingEnumerable<User>(connectionString, commandText, parameters, rowMappingDelegate);
        }
    }  
}

 

上面的使用范例,展示如何使用实做章节完成的SqlLazyRowMappingEnumerable。SqlLazyRowMappingEnumerable只需要四个参数,就可以对Sql数据库做查询数据以及完成ORM的工作。

 

范例中每次读取一个数据对象就暂停2秒,并且输出数据对象的读取时间与生成时间。在执行结果中可以看到,每个数据对象读取的时间与生成的时间是相同的。也就是说:每次透过SqlLazyRowMappingEnumerable取得的数据对象,都是在取得的当下才去生成数据对象。这样可以避免一次将所有数据对象加载到内存内,造成内存不足的风险。

 

可以说SqlLazyRowMappingEnumerable帮助开发人员简单的处理了,对Sql数据库查询大量数据做ORM的需求。

 

实做

范列下载

实做说明请参照范例程序内容:LazyRowMappingSample点此下载

 

范例结构

下图是简易的范例结构,对照这张图片说明与范例程序,可以帮助开发人员较快速理解本篇文章的思路。

 

LazyDataRecordEnumerable

读取资料可以使用ADO.NET里的DbDataReader类别,来与关连式数据库做连接。开发人员去分析ADO.NET里提供的DbDataReader类别,可以发现DbDataReadr类别是以一次读取一笔数据的方式来处理数据库数据,这看起来能满足查询大量数据的需求。而这个功能主要是由DbDataReader类别实做的IDataReader接口跟IDataRecord接口所定义;IDataReader接口定义了询览下一笔数据的方法、IDataRecord接口则是定义取得数据内容的方式。

 

初步了解DbDataReader类别的运作模式之后,来看看下列这个LazyDataRecordEnumerable对象,LazyDataRecordEnumerable将DbDataReader类别的运作模式封装成为IEnumerable<IDataRecord>的实做。系统在使用foreach列举IEnumerable<IDataRecord>的时候,LazyDataRecordEnumerable才会建立DbDataReader去关连式数据库查询数据。然后以一次读取一笔数据的方式,将数据库数据透过IDataRecord交由系统使用。

 

关于LazyDataRecordEnumerable的设计细节,可以参考:
[.NET] LINQ Deferred Execution

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
 
namespace LazyRowMappingSample
{
    public abstract class LazyDataRecordEnumerable: IEnumerable<IDataRecord>
    {
        // Methods
        protected abstract LazyDataRecordEnumerator CreateEnumerator();
 
        public IEnumerator<IDataRecord> GetEnumerator()
        {
            return this.CreateEnumerator();
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }       
    }
 
    public abstract class LazyDataRecordEnumerator : IEnumerator<IDataRecord>
    {
        // Constructor      
        public void Dispose()
        {
            this.EndEnumerate();
        }
 
 
        // Properties
        protected abstract DbDataReader DataReader { get; }
 
        public IDataRecord Current
        {
            get
            {
                return this.DataReader;
            }
        }
 
        object System.Collections.IEnumerator.Current
        {
            get
            {
                return this.Current;
            }
        }
 
 
        // Methods
        protected abstract void BeginEnumerate();
 
        protected abstract void EndEnumerate();                     
 
        public bool MoveNext()
        {
            if (this.DataReader == null) this.BeginEnumerate();
            if (this.DataReader != null)
            {
                while (this.DataReader.Read() == true)
                {
                    return true;
                }
            }
            return false;
        }
 
        public void Reset()
        {
            this.EndEnumerate();
        }
    }   
}

 

*LazyDataRecordEnumerable也可以使用.NET提供的yield关键词来实做,有兴趣的开发人员可以找相关数据来学习。

 

CastingEnumerable

LazyDataRecordEnumerable实做的IEnumerable<IDataRecord>接口所提供的IDataRecord,并不是开发人员想要得到的数据对象。要将IDataRecord转换为数据对象,可以在LazyDataRecordEnumerable外面套用一层CastingEnumerable。透过CastingEnumerable提供的功能,以一次一笔的方式,将LazyDataRecordEnumerable提供的IDataRecord转变成为数据对象交由系统使用。

 

关于CastingEnumerable的设计细节,可以参考:
[.NET] CastingEnumerable

 

LazyRowMappingEnumerable

LazyDataRecordEnumerable套用一层CastingEnumerable的方式,已经可以完成Lazy Row Mapping的功能。但为了让开发人员方便使用,另外建立了一个LazyRowMappingEnumerable,用来封装了LazyDataRecordEnumerable、CastingEnumerable的生成跟运作。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
 
namespace LazyRowMappingSample
{
    public abstract class LazyRowMappingEnumerable<T> : IEnumerable<T>
        where T : class
    {
        // Fields
        private readonly Func<IDataRecord, T> _rowMappingDelegate = null;
 
        private IEnumerable<T> _enumerable = null;
 
 
        // Constructor  
        public LazyRowMappingEnumerable(Func<IDataRecord, T> rowMappingDelegate)
        {
            #region Require
 
            if (rowMappingDelegate == null) throw new ArgumentNullException();
 
            #endregion
            _rowMappingDelegate = rowMappingDelegate;
        }
 
 
        // Methods
        protected abstract LazyDataRecordEnumerable CreateEnumerable();
 
        private T CreateObject(IDataRecord dataRecord)
        {
            return _rowMappingDelegate(dataRecord);
        }
 
        public IEnumerator<T> GetEnumerator()
        {
            if (_enumerable == null)
            {
                LazyDataRecordEnumerable lazyDataRecordEnumerable  = this.CreateEnumerable();
                CastingEnumerable<T, IDataRecord> castingEnumerable = new CastingEnumerable<T, IDataRecord>(lazyDataRecordEnumerable, this.CreateObject);
                _enumerable = castingEnumerable;
            }
            return _enumerable.GetEnumerator();
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
}

 

SqlLazyRowMappingEnumerable

一直到建立LazyDataRecordEnumerable为止,整个范例处理目标都是抽象的DbDataReader,而不是连接各种数据库的DbDataReader实做。最后一个范例,就用来说明如何建立LazyRowMappingEnumerable的Sql版本实做。开发人员使用这个SqlLazyRowMappingEnumerable,就可以简单处理对Sql数据库查询大量数据做ORM的需求。

 

关于SqlLazyRowMappingEnumerable的设计细节,可以参考:
KB-当心SqlDataReader.Close时的额外数据传输量 - 黑暗线程

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
 
namespace LazyRowMappingSample
{
    public class SqlLazyRowMappingEnumerable<T> : LazyRowMappingEnumerable<T>
        where T : class
    {
        // Fields
        private readonly string _connectionString = null;
 
        private readonly string _commandText = null;
 
        private readonly SqlParameter[] _parameters = null;       
 
 
        // Constructor    
        public SqlLazyRowMappingEnumerable(string connectionString, string commandText, SqlParameter[] parameters, Func<IDataRecord, T> rowMappingDelegate)
            : base(rowMappingDelegate)
        {
            #region Require
 
            if (string.IsNullOrEmpty(connectionString) == true) throw new ArgumentException();
            if (string.IsNullOrEmpty(commandText) == true) throw new ArgumentException();
            if (parameters == null) throw new ArgumentNullException();
 
            #endregion
            _connectionString = connectionString;
            _commandText = commandText;
            _parameters = parameters;
        }
 
 
        // Methods
        protected override LazyDataRecordEnumerable CreateEnumerable()
        {
            return new SqlLazyDataRecordEnumerable(_connectionString, _commandText, _parameters); 
        }
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
 
namespace LazyRowMappingSample
{
    public class SqlLazyDataRecordEnumerable : LazyDataRecordEnumerable
    {
        // Fields
        private readonly string _connectionString = null;
 
        private readonly string _commandText = null;
 
        private readonly SqlParameter[] _parameters = null;
 
 
        // Constructor    
        public SqlLazyDataRecordEnumerable(string connectionString, string commandText, SqlParameter[] parameters)
        {
            #region Require
 
            if (string.IsNullOrEmpty(connectionString) == true) throw new ArgumentException();
            if (string.IsNullOrEmpty(commandText) == true) throw new ArgumentException();
            if (parameters == null) throw new ArgumentNullException();
 
            #endregion
            _connectionString = connectionString;
            _commandText = commandText;
            _parameters = parameters;
        }
 
 
        // Methods
        protected override LazyDataRecordEnumerator CreateEnumerator()
        {
            return new SqlLazyDataRecordEnumerator(_connectionString, _commandText, _parameters);
        }
    }
 
    public class SqlLazyDataRecordEnumerator : LazyDataRecordEnumerator
    {
        // Fields
        private readonly string _connectionString = null;
 
        private readonly string _commandText = null;
             
        private readonly  SqlParameter[] _parameters = null;
 
        private SqlConnection _connection = null;
 
        private SqlCommand _command = null;
 
        private SqlDataReader _dataReader = null;
 
 
        // Constructor    
        public SqlLazyDataRecordEnumerator(string connectionString, string commandText, SqlParameter[] parameters)
        {
            #region Require
 
            if (string.IsNullOrEmpty(connectionString) == true) throw new ArgumentException();
            if (string.IsNullOrEmpty(commandText) == true) throw new ArgumentException();
            if (parameters == null) throw new ArgumentNullException();
 
            #endregion
            _connectionString = connectionString;
            _commandText = commandText;
            _parameters = parameters;
        }
 
 
        // Properties
        protected override DbDataReader DataReader
        {
            get { return _dataReader; }
        }
 
 
        // Methods
        protected override void BeginEnumerate()
        {
            // End
            this.EndEnumerate();
 
            // Begin
            _connection = new SqlConnection(_connectionString);
            _command = new SqlCommand(_commandText, _connection);
            _command.Parameters.AddRange(_parameters);
            _connection.Open();
            _dataReader = _command.ExecuteReader();
        }
 
        protected override void EndEnumerate()
        {
            // End
            if(_dataReader!=null)
            {
                _command.Cancel();
                _dataReader.Close();
                _dataReader.Dispose();
                _dataReader = null;
            }
             
            if(_command!=null)
            {
                _command.Dispose();
                _command = null;
            }
 
            if(_connection!=null)
            {
                _connection.Close();
                _connection.Dispose();
                _connection = null;
            }
        }
    }
}

 

后记

了解整个LazyRowMappingEnumerable的运作之后,开发人员遇到对关系数据库查询大量数据做ORM的需求。如果目标关系数据库有提供DbDataReadr对象来查询数据,开发人员可以实做LazyRowMappingEnumerable的子类别来满足需求。如果没有提供DbDataReadr对象或是根本不是关系数据库,也可以依照本章的思路建立一个LazyXxxMappingEnumerable来完成这个功能需求。

 

 

 


期許自己~
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。


 

 

分类: .NET

摘要: 前言在做架构设计的时候,数据对象进出系统边界,可以采用先前的文章介绍的[Architecture Pattern] Repository,来将外部的系统、模块、数据库…等等,隔离在架构之外。而当系统采用关系数据库来做为储存数据库的时候,开发人员必需要在程序内加入ORM(Object Relational Mapping)的功能,才能将数据对象与关系数据库数据做互相的转换。但当开发人员要从数据库查询大量数据的时候,会惊觉上述ORM的运作模式是:将数据库查询到的「所有数据」,转换为数据对象集合放在「内存内」,再交由系统去使用。「所有数据」、「内存内」这两个关键词,决定了在大量数据的处理上,这个运作阅读全文
posted @ 2012-05-06 14:26 Clark159 阅读(545) | 评论 (0) 编辑
 
摘要: 前言在前一个章节[.NET] XAML(1)--对象生成,介绍了「XAML对象生成」这个简单却强大的对象生成模式。透过这个XAML对象生成配合面向对象的对象设计,可以让开发人员依照XAML内容生成近乎无限组合的对象。但是光只有前一个章节介绍的内容,在实际的开发应用上,很快就会遇到不足的地方。假设现在要使用Property-Element的设定,将TextBlock 的Text设定为.NET里的Null,开发人员可能会写出下面范例的XAML。<TextBlock x:Name="ShowTextBlock" FontSize="72"> <阅读全文
posted @ 2012-04-21 15:06 Clark159 阅读(753) | 评论 (0) 编辑
 
摘要: 前言XAML是微软推出的一种宣告式标记语言,采用XML的格式让开发人员设计应用程序编程接口。在微软近期推出的各种开发平台,例如WPF、Silverlight、WP7、甚至Win8的Metro style app开发上都可以看到XAML的身影。XAML可以这么的神奇的跨平台运作,是因为XAML不涉足执行平台的运作、机制...等等,只单纯的依照开发人员的设计,建立对应的对象让执行平台使用。例如:XAML范例<phone:PhoneApplicationPage x:Class="XamlSample.MainPage" xmlns="http://schemas阅读全文
posted @ 2012-04-10 22:33 Clark159 阅读(845) | 评论 (2) 编辑
 
摘要: 撰写多线程对象时,执行速度是一项很重要的设计考虑。通常为了加快执行速度,会将执行运作逻辑的主线程,跟发出事件的事件线程做隔离设计。这样的隔离设计可以不让主线程,因为外部事件处理而停顿。而这样的设计下,为了简化线程管理,可以采用ThreadPool来完成事件线程的工作。简单的程序范例如下:namespace ConsoleApplication1{ class Program { static void Main(string[] args) { var obj = new ClassA(); obj.Notif...阅读全文
posted @ 2012-03-22 12:50 Clark159 阅读(1150) | 评论 (8) 编辑
 
摘要: 前言 :Log4net是一个很方便用来做Log的第三方软件。 但在输出讯息的部分,却很吊诡的「部分支持」输出 Tab符号(Tab Character)。 所谓的「部分支持」是说, 在讯息内容的部分有支持,但是讯息Layout的部分不支持。 这让开发人员做讯息排版的时候,受到很大的限制。本篇文章记录, 如何在使用Log4net输出Log讯息的时候,能够让支持 Tab符号(Tab Character)。 希望能帮助有需要的开发人员。实做 :实做的方式,主要是使用 Log4net自定义参数的功能, 加入自定义的 Tab符号(Tab Character),来达成支持讯息输出 Tab符号(Tab Cha阅读全文
posted @ 2012-01-15 14:44 Clark159 阅读(891) | 评论 (0) 编辑
 
摘要: 前言 :看到91跟小朱都分享了,延迟执行的文章。 - 91 : [.NET]延迟执行(Deferred Execution) 简单概念实作 - 小朱 :[.NET] LINQ 的延迟执行 (Deferred Execution) 唤醒了许久之前的记忆,记得也有对LINQ的运作下了一番功夫。 趁记忆还没有消失。简单的做个记录,也希望对有需要的开发人员有帮助。说明 :简单的说,在 Linq的延迟执行运作,主要有三个要点。 1. IEnumerable跟 foreach是 LINQ运作的核心。 2. IEnumerable套用 Decorator模式,对IEnumerable加入功能。 3. 使用.阅读全文
posted @ 2012-01-12 18:26 Clark159 阅读(75) | 评论 (0) 编辑
 
摘要: 前言 : 最近在处理应用程序安装的相关问题。 系统内有使用Window Time Service来完成时间同步的功能。但在启动这个服务的时候。 却发现使用ManagementObject Class控制 WMI的这种方式, 无法将Windows Service启动类型设定为「自动(延迟开始)」。使用Google搜寻之后, 找到了可以使用 Windows SC命令,来做Windows Service的管理。 并且这个方式,可以将Windows Service启动类型设定为「自动(延迟开始)」。本篇文章简单纪录, .NET应用程序如何使用Windows SC命令,来做Windows Service阅读全文
posted @ 2012-01-04 13:59 Clark159 阅读(213) | 评论 (0) 编辑
 
摘要: 前言 : 最近为了多执行绪程序分享数据集合,搞的焦头烂额。 主要的问题点卡在, 当有一条执行绪使用 foreach列举数据集合的时候,另外一条执行绪去变更数据集合。 这时候会发生Exception,通知说在列举的同时数据集合被变更。当下最先想到的解决方案是,使用lock在读写数据集合的时候做锁定。 这样的确可以解决问题, 但是因为不论读写都先lock,这样会降低程序执行的效能。 并且这样的写法,要求使用数据集合的程序代码必须要记得做lock动作,不然会发生错误。上网搜寻到这篇「再谈程序多任务(III)─执行绪安全与数据集合」,刚好解决了我遇到的问题点。:D整篇文章主要的思路就是, ...阅读全文
posted @ 2011-12-11 18:31 Clark159 阅读(145) | 评论 (0) 编辑
 
摘要: 前言 : 我们在撰写自定义 Configuration时,会先定义好对应的自定义 ConfigurationSection 与 Config档让程序代码知道该如何颇析数据。<sample propertyA="Clark001"> <propertyCollectionB> <add name="Clark002" value="Clark003" /> </propertyCollectionB> </sample>public class SampleSection : 阅读全文
posted @ 2011-10-10 10:03 Clark159 阅读(26) | 评论 (0) 编辑
 
摘要: 前言 :自定义Configuration区段的数据读取,先前小朱有写了一系列的文章。本篇文章描述,如何使用程序代码做自定义Configuration的数据写入。注意 :在 Microsoft Visual Studio IDE除错环境下,执行程序写入.config时。程序写入的将会是*.vshost.exe.config,而不是预期中的 *.exe.config。并且程序执行结束之后,IDE会覆盖*.vshost.exe.config成为写入前的状态。因此会误认为程序执行失败。只要编译完毕之后,点选bin目录底下的*.exe执行。再去检查*.exe.config,就可以看到预期中的结果。相关资阅读全文
posted @ 2011-10-10 09:54 Clark159 阅读(28) | 评论 (0) 编辑
 
摘要: 前言 :VS2010内建了测试项目,本篇文章说明测试项目的生命周期。生命周期图 :生命周期范例 :[TestClass]public class UnitTest1{ [AssemblyInitialize()] public static void AssemblyInitialize(TestContext context) { MessageBox.Show("AssemblyInitialize"); } [ClassInitialize()] public static void ClassInitialize(TestContext...阅读全文
posted @ 2011-10-10 09:26 Clark159 阅读(29) | 评论 (0) 编辑
 
摘要: 前言 :应用程序在Vista或是Win7上执行时,有时会有权限不足的问题。 简单的解法是请用户在应用程序图标上右键单击,然后选择以系统管理员身分执行。 但这个动作常常会被使用者忘记。这个问题在VS2008或是VS2010上已经有了解决方案 : (请参考) http://social.msdn.microsoft.com/Forums/zh-TW/1007/thread/ce70e22d-45f7-4903-b8f4-76a159d3002d http://www.dotblogs.com.tw/jjnnykimo/archive/2009/05/08/8346.aspx http://www.阅读全文
posted @ 2011-10-10 09:22 Clark159 阅读(30) | 评论 (0) 编辑
 
摘要: 实作 :1. 建立Windows应用程序项目 2. 建立数据对象 *建立完毕,先建置方案一次。 3. 建立数据源 4. 建立报表 5. 系结报表数据源 *从右边数据源,拖曳数据字段至报表 6. 建立报表窗体 *选择报表后会自动建立TestDataBindingSource7. 建立报表数据 8. 捡视报表阅读全文
posted @ 2011-10-10 09:20 Clark159 阅读(19) | 评论 (0) 编辑
 
摘要: 前言 :在面向对象的程序开发设计上,我们常常强调重用与抽换 : 重用核心的程序代码,抽换特定的模块。但是大多的面向对象的书,只有介绍重用与抽换的理论,并没有介绍实做的时候该怎么写。因为实际开发系统,要完成重用与抽换。牵扯到系统设计、动态加载、Config管理......等等方方面的知识。真的要解释起来,需要的篇幅会是很大一篇。本篇的文章跳过这些复杂的理论面,逐步解说如何实做微软提供的Provider Pattern来实现对象的抽换。Provider Pattern提供了,使用App.config或是web.config来做储存装置,并且实做了对象抽换的功能。依照本篇的模块去做面向对象开发设计的阅读全文
posted @ 2011-10-10 09:13 Clark159 阅读(18) | 评论 (0) 编辑
 
摘要: 前言 :写程序难免,会遇到要使用自定义函式来作对象数组转型。 写了一个对象来做这个动作,跟大家分享。说明 :这个对象的特点为: 1. 使用到才转型。不会在内存,建立整个转型后的数组副本。 2. 可在转型时加入参数。使用范例 :namespace CLK.Collections.ConsoleApplication{ public class User { public string LastName = string.Empty; public string FirstName = string.Empty; } public class D...阅读全文
posted @ 2011-10-10 09:04 Clark159 阅读(12) | 评论 (0) 编辑
 
摘要: 前言 :处理AD数据的时候 常常会需要取得用户的Domain\User数据 可是用户的AD属性却没有这个数据 本篇文章的程序示范,如何取得用户的Domain\User。实作 :using System;using System.Collections.Generic;using System.Text;using System.DirectoryServices;using System.Security.Principal;namespace ConsoleApplication1{ class Program { static void Main(string[]...阅读全文
posted @ 2011-10-10 08:49 Clark159 阅读(27) | 评论 (0) 编辑
 
摘要: 问题 :依照微软技术支持服务这篇文章 如何在 Visual Basic.NET 或 Visual Basic 2005 建立安装项目的 Windows 服务http://support.microsoft.com/kb/317421/zh-tw 建立Windows Service的安装项目 安装之后在计算机的服务里,找不到安装的服务解法 :第一种 : 手动执行 installutil.exe 第二种 : 在安装项目建立自定义动作,项目选择 Windows Service项目的主要输出。 以上两种解法都可以将Windows Service安装在目标计算机上阅读全文
posted @ 2011-10-10 08:46 Clark159 阅读(23) | 评论 (0) 编辑
 
摘要: 前言 :一般在监控文件夹或是档案异动,大多使用FileSystemWatcher类别 但FileSystemWatcher在监控档案建立的事件时 他发出的 Created事件的时间点,是在档案建立开始的当时,而不是档案建立完毕的时间点。 如果直接使用的话,有时会造成建立档案的线程跟监控档案的线程互相冲突 造成『由于另一个进程正在使用档案』的例外产生。改为本篇文章介绍的使用方法及可避免上述问题实作 :using System; using System.Collections.Generic; using System.Text; using System.IO; namespace Cons.阅读全文
posted @ 2011-10-10 08:44 Clark159 阅读(20) | 评论 (0) 编辑
posted on 2012-05-06 23:29  HackerVirus  阅读(250)  评论(0编辑  收藏  举报