解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# CsvDb ʹÓÃÊÖ²á
±¾Îĵµ»ùÓÚÔ´Âë `NewLife.Core/IO/CsvDb.cs` ÓëÆäÒÀÀµ `NewLife.Core/IO/CsvFile.cs`£¬ÓÃÓÚ˵Ã÷ `CsvDb<T>`£¨CSV ÎļþÇáÁ¿¼¶Êý¾Ý¿â£©µÄÉè¼ÆÄ¿±ê¡¢Êý¾Ý¸ñʽ¡¢ÊÂÎñÄ£ÐÍÓë CRUD Ó÷¨¡£
> ¹Ø¼ü´Ê£º×·¼Óд¡¢¸ßÐÔÄÜ˳Ðò²éѯ¡¢Ìø¹ýËð»µÐС¢±íÍ·Ó³Éä¡¢ÊÂÎñ»º´æ¡¢·´É仺´æ¡¢ÐòÁл¯ÊôÐÔÃû¡£
---
## 1. ¸ÅÊö
`CsvDb<T>` ÊÇÒ»¸öÒÔ CSV Îļþ×÷Ϊ³Ö¾Ã»¯´æ´¢µÄ¡°ÇáÁ¿¼¶Êý¾Ý¿â¡±£¬Êʺϣº
- ´óÁ¿Êý¾ÝÐèÒª **¿ìËÙ×·¼Ó£¨Append£©**£»
- ÐèÒª **˳ÐòɨÃèʽ¿ìËÙ²éѯ**£¨`Query`£©£»
- ºÜÉÙÐÞ¸Ä/ɾ³ý£¨ÐÞ¸Ä/ɾ³ý±¾ÖÊÊÇ¡°È«Á¿ÖØÐ´¡±£©£»
- ×ÀÃæ¶Ë³¡¾°£¬SQLite µÈ¹ØÏµ¿â¿ÉÄÜÒò·Ç·¨¹Ø»úµ¼ÖÂË𻵣»`CsvDb<T>` ¶Áȡʱ¿É **Ìø¹ýËð»µÐÐ**£¬Ìá¸ß¿É»Ö¸´ÐÔ¡£
ÖØÒªÔ¼Êø£º
- **²»Ö§³ÖḬ̈߳²È«**£ºÀà×¢ÊÍÃ÷È·ÒªÇó¡°Îñ±ØÈ·±£µ¥Ï̲߳Ù×÷¡±¡£Ô´ÂëÖв¿·Ö·½·¨Ê¹Óà `lock (this)` ·À²¢·¢£¬µ«²¢·ÇÍêÕû²¢·¢Éè¼Æ¡£
---
## 2. Êý¾ÝÎļþ¸ñʽ
### 2.1 ÎļþÍ·£¨Header£©
Ê×ÐÐÊÇÁÐÃû£¬À´Ô´ÓÚʵÌå `T` µÄ¹«¹²ÊµÀýÊôÐÔ£º
- ͨ¹ý·´É仺´æ `_properties = typeof(T).GetProperties(...)` »ñÈ¡ÊôÐÔ£»
- ÁÐÃûʹÓà `SerialHelper.GetName(PropertyInfo)`£¨¶ø²»ÊÇÊôÐÔÃû£©£¬ÒÔ±£³ÖÓëÐòÁл¯Ãû/ÌØÐÔÒ»Ö¡£
дÎļþʱ£º
- µ±ÎļþΪ¿Õ£¨`FileStream.Position == 0`£©Ê±Ð´Èë±íÍ·¡£
¶ÁÈ¡Îļþʱ£º
- Ê×ÐÐ×÷Ϊ CSV ÁÐÃû£»
- ½¨Á¢¡°ÎļþÁÐ -> ÊôÐÔË÷Òý¡±µÄÓ³ÉäÊý×é `columnToProperty`£¬±ÜÃâÿÐж¼²é×ֵ䡣
### 2.2 Êý¾ÝÐУ¨Data Rows£©
ÿÐжÔÓ¦Ò»¸ö `T` ʵÀý¡£
дÈëʱ£º
- Èô `T` ʵÏÖ `IModel`£º°´ÊôÐÔÃû `src[e.Name]` ¶Áȡֵ£»
- ·ñÔòͨ¹ý·´Éä `item.GetValue(e)` ¶ÁÈ¡ÊôÐÔÖµ¡£
¶Áȡʱ£º
- ´´½¨ `new T()`£»
- ¶ÔÿÁг¢ÊÔ°´Ä¿±êÊôÐÔÀàÐÍ×ö»ù´¡Ð£Ñ飨ÕûÊý/¸¡µã/ÈÕÆÚµÈ£©£¬Ð£Ñéʧ°ÜÔòÌø¹ý¸Ã×ֶΣ»
- ½«×Ö·û´® `raw` ת»»ÎªÄ¿±êÀàÐÍ£º`raw.ChangeType(pi.PropertyType)`£»
- ÔÙͨ¹ý `IModel` »ò `model.SetValue(pi, value)` ¸³Öµ¡£
---
## 3. ºËÐÄÊôÐÔ
### 3.1 `FileName`
- ÀàÐÍ£º`String?`
- ÓïÒ壺CSV Êý¾ÝÎļþ·¾¶
ʹÓÃÒªÇó£º
- ±ØÐëÉèÖã»Î´ÉèÖõ÷ÓûáÅ׳ö `ArgumentNullException`£¨¼û `GetFile()`£©¡£
### 3.2 `Encoding`
- ÀàÐÍ£º`Encoding`
- ĬÈÏ£º`Encoding.UTF8`
Ó°Ï죺
- ¶ÁÈ¡ÓëдÈë CSV ʱ´«µÝ¸ø `CsvFile.Encoding`¡£
### 3.3 `Comparer`
- ÀàÐÍ£º`IEqualityComparer<T>`
- ĬÈÏ£º`EqualityComparer<T>.Default`
ÓÃ;£º
- `Remove(T)` / `Remove(IEnumerable<T>)` / `Find(T)` / `Set(T, ...)` ÓÃËüÀ´Åжϡ°ÊµÌåÊÇ·ñÏàͬ¡±¡£
¿Éͨ¹ý¹¹Ô캯Êý `CsvDb(Func<T?, T?, Boolean> comparer)` ´«Èë×Ô¶¨Òå±È½ÏÂß¼¡£
---
## 4. ÊÂÎñÄ£ÐÍ£¨»º´æÐ´£©
### 4.1 `BeginTransaction()`
- ÐÐΪ£º°Ñµ±Ç°ÎļþÈ«²¿Êý¾Ý¶ÁÈëÄڴ棨`_cache = FindAll().ToList()`£©¡£
- Ö®ºóµÄ `Add/Remove/Set/Clear/Find/Query` ½«»ùÓÚ»º´æ²Ù×÷£¨±ÜÃâÆµ·± I/O£©¡£
### 4.2 `Commit()`
- ÐÐΪ£º°Ñ `_cache` ¸²¸Çд»ØÎļþ£¨`Write(_cache, false)`£©£¬È»ºóÇå¿Õ»º´æ¡£
### 4.3 `Rollback()`
- ÐÐΪ£º½öÇå¿Õ»º´æ£¬²»Ð´»Ø´ÅÅÌ¡£
### 4.4 Dispose ×Ô¶¯Ìá½»
`CsvDb<T>` ¼Ì³Ð `DisposeBase`£¬Æä `Dispose(Boolean)` ¸²¸ÇÖлáµ÷Óà `Commit()`£º
- Èô¿ªÆô¹ýÊÂÎñÇÒÈÔÓлº´æ£¬ÊͷŶÔÏóʱ»á×Ô¶¯Ìá½»£¨±£³ÖÀúÊ·¼æÈÝÐÐΪ£©¡£
½¨Ò飺
- ¶Ô¡°Åú´¦Àí¡±ÎªÖ÷µÄ³¡¾°£¬½¨ÒéÏÔʾµ÷Óà `Commit()`£¬±ÜÃâÒ쳣ʱÎóÌá½»¡£
---
## 5. дÈë/×·¼Ó
### 5.1 `Write(IEnumerable<T> models, Boolean append)`
ÓïÒ壺ÅúÁ¿Ð´Èë¡£
¹Ø¼üµã£º
- ´ò¿ªÎļþ·½Ê½£º`FileMode.OpenOrCreate` + `FileAccess.ReadWrite` + `FileShare.ReadWrite`£»
- `append=true` Ê±ÒÆ¶¯µ½Îļþβ£º`fs.Position = fs.Length`£»
- ÎļþΪ¿ÕʱдÈë±íÍ·£»
- дÍêºóÖ´ÐÐ `fs.SetLength(fs.Position)`£º
- ¸²¸Çд£¨`append=false`£©³¡¾°£º½Ø¶ÏÔÎļþ¶àÓಿ·Ö£»
- ×·¼ÓдʱҲ»á°Ñ³¤¶ÈÉèÖÃΪµ±Ç°Î»Öã¨Í¨³£µÈ¼Û£©¡£
### 5.2 `Add(T model)` / `Add(IEnumerable<T> models)`
- ÈôÒÑ `BeginTransaction()`£º½ö×·¼Óµ½ `_cache`£»
- ·ñÔò£ºÖ±½Ó `Write(..., append:true)`£¬ÐÔÄÜ×îºÃ¡£
---
## 6. ²éѯ
### 6.1 `IEnumerable<T> Query(Func<T, Boolean>? predicate, Int32 count = -1)`
ÓïÒ壺˳ÐòɨÃè²éѯ£¬°´Ðè·µ»Ø¡£
ÐÐΪҪµã£º
- ¿ªÆôÊÂÎñ£¨`_cache!=null`£©Ê±£º´Ó»º´æÃ¶¾Ù£¬ÃüÖÐÔò `yield return`£»
- 먦ÆôÊÂÎñʱ£º
- ʹÓà `CsvFile.ReadLine()` Öð¼Ç¼¶ÁÈ¡£»
- Ê×Ìõ¼Ç¼×÷Ϊ±íÍ·£»
- ºóÐøÃ¿Ìõ¼Ç¼¸ù¾ÝÓ³ÉäÌî³äµ½Ð¶ÔÏó¡£
Ëð»µÐд¦Àí£º
- ÀàÐÍת»»¹ý³ÌÖÐÈκÎÒì³£»á±»²¶»ñ²¢¼Ç¼£¨`XTrace.WriteException(ex)`£©£¬¸ÃÐÐÌø¹ý£»
- ÈôÒ»ÐÐÖÐûÓÐÈκÎ×ֶγɹ¦Æ¥Å䣨`success == 0`£©£¬ÊÓΪËð»µÐв¢Ìø¹ý¡£
`count`£º
- ĬÈÏ `-1` ±íʾ²»ÏÞÖÆ£»
- ÿ `yield` Ò»´Îºó `--count`£¬µ½ 0 ½áÊø¡£
### 6.2 `T? Find(Func<T, Boolean>? predicate)`
- µÈ¼ÛÓÚ `Query(predicate, 1).FirstOrDefault()`¡£
### 6.3 `IList<T> FindAll()`
- ¿ªÆôÊÂÎñʱ·µ»Ø»º´æ¸±±¾ `_cache.ToList()`£»
- ·ñÔò¶Áȡȫ²¿¡£
### 6.4 `Int32 FindCount()`
- ·ÇÊÂÎñ³¡¾°£ºÊ¹Óà `StreamReader.ReadLine()` ÖðÐмÆÊý£¨Ìø¹ýÍ·²¿£©¡£
- ×¢Ò⣺ÕâÀï°´ÎïÀíÐмÆÊý£¬²»¿¼ÂÇ CSV ÒýºÅ×Ö¶ÎÄÚ»»ÐеÄÇé¿ö£»ÔÚ³£¹æ±í¸ñÐÍ CSV ÖÐͨ³£¿É½ÓÊÜ¡£
---
## 7. ¸üÐÂÓëɾ³ý£¨È«Á¿ÖØÐ´£¬½ÏÂý£©
### 7.1 `Remove(Func<T, Boolean> predicate)`
- Èô¿ªÆôÊÂÎñ£º¶Ô `_cache` Ö´ÐÐ `RemoveAll`£»
- ·ñÔò£º
- `FindAll()` ¶ÁÈëÈ«²¿£»
- ¹ýÂ˵ôÃüÖÐÏ
- ÔÙ `Write(list, false)` ¸²¸Çд»Ø¡£
### 7.2 `Update(T model)` / `Set(T model)`
- `Update`£ºÖ»¸üУ¬²»´æÔÚÔò·µ»Ø `false`£»
- `Set`£º´æÔÚÔò¸üУ¬²»´æÔÚÔò×·¼ÓÒ»Ìõ¡£
먦ÆôÊÂÎñʱ£º
- ¶Áȡȫ²¿µ½Äڴ棬Ð޸ĺ󸲸Çд»Ø¡£
---
## 8. Òì²½²éѯ£¨net5+ / netstandard2.1+£©
ÔÚ `NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER` ÏÂÌṩ£º
- `IAsyncEnumerable<T> QueryAsync(Func<T, Boolean>? predicate, Int32 count = -1)`
- `Task<IList<T>> FindAllAsync()`
ʵÏÖÒªµã£º
- ÄÚ²¿Ê¹Óà `CsvFile.ReadAllAsync()`£»
- Í·²¿Ó³ÉäÂß¼Óëͬ²½°æÒ»Ö£»
- ·¢ÉúÒ쳣ʱͬÑù¼Ç¼²¢Ìø¹ýÐС£
---
## 9. ×îСʾÀý
### 9.1 ¶¨ÒåʵÌå
```csharp
public class User
{
public Int32 Id { get; set; }
public String? Name { get; set; }
public DateTime CreateTime { get; set; }
}
```
### 9.2 ×·¼ÓдÈë
```csharp
using NewLife.IO;
var db = new CsvDb<User>
{
FileName = "./user.csv",
Encoding = Encoding.UTF8,
};
db.Add(new User { Id = 1, Name = "Stone", CreateTime = DateTime.Now });
db.Add(new User { Id = 2, Name = "NewLife", CreateTime = DateTime.Now });
```
### 9.3 ²éѯ
```csharp
foreach (var u in db.Query(e => e.Id > 0))
{
Console.WriteLine($"{u.Id} {u.Name}");
}
```
### 9.4 Åú´¦ÀíÊÂÎñ
```csharp
using var db = new CsvDb<User> { FileName = "./user.csv" };
db.BeginTransaction();
db.Add(new User { Id = 3, Name = "Tx" });
db.Remove(e => e.Id == 1);
db.Commit();
```
---
## 10. ×¢ÒâÊÂÏîÓë×î¼Ñʵ¼ù
1. **¸ßƵдÈëÓÅÏÈÓà `Add`£¨·ÇÊÂÎñ£©**£ºËü×ß×·¼Óд·¾¶£¬±ÜÃâÈ«Á¿ÖØÐ´¡£
2. **ÐÞ¸Ä/ɾ³ýÊÇÒ»ÖÖ¡°Åú´¦Àí²Ù×÷¡±**£º½¨Òé `BeginTransaction()` ºó¼¯Öд¦Àí£¬ÔÙ `Commit()`¡£
3. **µ¥Ïß³ÌʹÓÃ**£º¼´Ê¹ÄÚ²¿ÓÐ `lock (this)`£¬Ò²²»½¨Òé¶àÏ̲߳¢·¢²Ù×÷ͬһ¸öʵÀý¡£
4. **±íÍ·ÁÐÃûÓëÊôÐÔÃû**£ºÐ´ÈëʹÓà `SerialHelper.GetName`£¬¶ÁÈ¡Êǰ´ÁÐÃûÓ³Éäµ½ÊôÐÔ£»ÈôÄã×Ô¶¨ÒåÁÐÃû£¨ÐòÁл¯ÌØÐÔ£©£¬ÒªÈ·±£Ð´Èë/¶ÁȡһÖ¡£
---
## 11. Ïà¹ØÁ´½Ó
- ÔÚÏßÎĵµ£º`https://newlifex.com/core/csv_db`
- Ô´Â룺`NewLife.Core/IO/CsvDb.cs`
- ÒÀÀµ£º`NewLife.Core/IO/CsvFile.cs`
|