前言
看了大家都在造轮子,我也要写一个站点自用了,没有数据库怎么办,又不想用Sqlite,所以自己造吧。大不了就是都文件到内存,然后内存到文件。
正文
对于这种操作,无非就是反射一下属性,然后通过对象和属性进行更新。当然EF也有这样的功能,不过对Model而言太臃肿了,这里就不用了。
上代码
1 /// <summary> 2 /// 文件系统数据库 3 /// 主键Attribute [Key],支持主键比较 4 /// </summary> 5 /// <typeparam name="T"></typeparam> 6 public class FileDbHelper<T> where T : class 7 { 8 private static List<T> dataList = new List<T>(); 9 private static string savePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", typeof(T).Name + ".mydb"); 10 private static JavaScriptSerializer js = new JavaScriptSerializer(); 11 12 static FileDbHelper() 13 { 14 string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data"); 15 if (!Directory.Exists(dir)) 16 { 17 Directory.CreateDirectory(dir); 18 } 19 20 string savePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", typeof(T).Name + ".mydb"); 21 if (File.Exists(savePath)) 22 { 23 string[] lines = File.ReadAllLines(savePath, Encoding.UTF8); 24 foreach (var line in lines) 25 { 26 if (!string.IsNullOrEmpty(line)) 27 { 28 try 29 { 30 dataList.Add(js.Deserialize<T>(line)); 31 } 32 catch { } 33 } 34 } 35 } 36 } 37 38 public static void Add(T model) 39 { 40 lock (dataList) 41 { 42 dataList.Add(model); 43 SaveFile(); 44 } 45 } 46 47 public static void AddList(List<T> list) 48 { 49 lock (dataList) 50 { 51 dataList.AddRange(list); 52 SaveFile(); 53 } 54 } 55 56 public static void AddOrUpdate(T model, params string[] args) 57 { 58 lock (dataList) 59 { 60 List<FileDbInfo> infoList = FindKeyDbList(model); 61 T equalModel = CheckKeyEqual(model, infoList); 62 if (equalModel == null) 63 { 64 Add(model); 65 } 66 else 67 { 68 Update(equalModel, model, args); 69 } 70 71 SaveFile(); 72 } 73 } 74 75 public static T QueryInfo(T model, params string[] args) 76 { 77 lock (dataList) 78 { 79 List<FileDbInfo> infoList = FindArgsDbList(model, args); 80 T equalModel = CheckKeyEqual(model, infoList, args); 81 82 return equalModel; 83 } 84 } 85 86 public static List<T> QueryList(int page, int pageSize, T model, params string[] args) 87 { 88 lock (dataList) 89 { 90 List<FileDbInfo> infoList = FindArgsDbList(model, args); 91 List<T> equalList = CheckArgsEqualList(model, infoList, args); 92 93 return equalList.Skip(pageSize * (page - 1)).Take(pageSize).ToList(); 94 } 95 } 96 97 private static void Update(T oldModel, T newModel, string[] args) 98 { 99 List<string> keyList = ReadKeyName(); 100 foreach (PropertyInfo pInfo in newModel.GetType().GetProperties()) 101 { 102 if (args.Length > 0) 103 { 104 if (!args.ToList().Contains(pInfo.Name)) 105 { 106 Object new_value = pInfo.GetValue(newModel, null); 107 pInfo.SetValue(oldModel, new_value, null); 108 } 109 } 110 else 111 { 112 if (!keyList.Contains(pInfo.Name)) 113 { 114 Object new_value = pInfo.GetValue(newModel, null); 115 pInfo.SetValue(oldModel, new_value, null); 116 } 117 } 118 } 119 } 120 121 private static T CheckKeyEqual(T model, List<FileDbInfo> infoList, string[] args = null) 122 { 123 foreach (var item in dataList) 124 { 125 bool is_equal = true; 126 foreach (var info in infoList) 127 { 128 if (args == null || (args != null && args.ToList().Contains(info.key))) 129 { 130 if (ReadString(model, info.key) != ReadString(item, info.key)) 131 { 132 is_equal = false; 133 break; 134 } 135 } 136 } 137 138 if (is_equal) 139 { 140 return item; 141 } 142 } 143 144 return null; 145 } 146 147 private static List<T> CheckArgsEqualList(T model, List<FileDbInfo> infoList, string[] args = null) 148 { 149 List<T> result = new List<T>(); 150 foreach (var item in dataList) 151 { 152 bool is_equal = true; 153 foreach (var info in infoList) 154 { 155 if (args == null || (args != null && args.ToList().Contains(info.key))) 156 { 157 if (ReadString(model, info.key) != ReadString(item, info.key)) 158 { 159 is_equal = false; 160 break; 161 } 162 } 163 } 164 165 if (is_equal) 166 { 167 result.Add(item); 168 } 169 } 170 171 return result; 172 } 173 174 private static List<FileDbInfo> FindKeyDbList(T model, params string[] args) 175 { 176 List<string> keyList = ReadKeyName(); 177 var infoList = new List<FileDbInfo>(); 178 foreach (var key in keyList) 179 { 180 if (args == null || (args != null && args.ToList().Contains(key))) 181 { 182 infoList.Add(new FileDbInfo(key, ReadString(model, key))); 183 } 184 } 185 186 return infoList; 187 } 188 189 private static List<FileDbInfo> FindArgsDbList(T model, params string[] args) 190 { 191 List<string> keyList = ReadArgsName(); 192 var infoList = new List<FileDbInfo>(); 193 foreach (var key in keyList) 194 { 195 if (args == null || (args != null && args.ToList().Contains(key))) 196 { 197 infoList.Add(new FileDbInfo(key, ReadString(model, key))); 198 } 199 } 200 201 return infoList; 202 } 203 204 private static List<string> ReadKeyName() 205 { 206 List<string> keyList = new List<string>(); 207 foreach (var pInfo in typeof(T).GetProperties()) 208 { 209 foreach (var attr in pInfo.GetCustomAttributes(false)) 210 { 211 if (attr.GetType() == typeof(KeyAttribute)) 212 { 213 keyList.Add(pInfo.Name); 214 } 215 } 216 } 217 218 if (keyList.Count == 0) 219 { 220 throw new Exception("未定义主键,通过设置注解来添加主键[Key],目前只支持int和string"); 221 } 222 223 return keyList; 224 } 225 226 private static List<string> ReadArgsName() 227 { 228 List<string> keyList = new List<string>(); 229 foreach (var pInfo in typeof(T).GetProperties()) 230 { 231 keyList.Add(pInfo.Name); 232 } 233 234 return keyList; 235 } 236 237 private static string ReadString(T model, string key_name) 238 { 239 PropertyInfo propertyInfo = model.GetType().GetProperty(key_name); 240 object obj = propertyInfo.GetValue(model, null); 241 if (propertyInfo.PropertyType == typeof(int)) 242 { 243 return obj.ToString(); 244 } 245 else if (propertyInfo.PropertyType == typeof(string)) 246 { 247 return obj.ToString(); 248 } 249 else 250 { 251 return obj.ToString(); 252 } 253 } 254 255 private static void SaveFile() 256 { 257 StringBuilder content = new StringBuilder(); 258 foreach (var item in dataList) 259 { 260 content.AppendLine(js.Serialize(item)); 261 } 262 263 File.WriteAllText(savePath, content.ToString(), new UTF8Encoding(false)); 264 } 265 } 266 267 public class FileDbInfo 268 { 269 public FileDbInfo(string key, string str_value) 270 { 271 this.key = key; 272 this.str_value = str_value; 273 } 274 275 public string key { get; set; } 276 277 public string str_value { get; set; } 278 } 279 280 public class KeyAttribute : Attribute { } 281 }
使用方式。
public class UserInfo2 { [Key] public string name { get; set; } public string pwd { get; set; } public int age { get; set; } public string info { get; set; } }
// 新增数据
FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test1", pwd = "12341", age = 10 }); FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test2", pwd = "12342", age = 10 }); FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test3", pwd = "12343", age = 11 }); FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test4", pwd = "12344", age = 12 }); FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test5", pwd = "12345", age = 10 });
// 查询集合,条件查询 var list = FileDbHelper<UserInfo2>.QueryList(1, 10, new UserInfo2() { age = 10 }, "age");
// 单个对象,条件查询 var model = FileDbHelper<UserInfo2>.QueryInfo(new UserInfo2() { age = 12 }, "age");
// 修改所有值 model.info = "hehe"; FileDbHelper<UserInfo2>.AddOrUpdate(model);
// 修改指定的值 FileDbHelper<UserInfo2>.AddOrUpdate(new UserInfo2() { name = "test1", age = 12 }, "age"); var model2 = FileDbHelper<UserInfo2>.QueryInfo(model);
总结:伟大出自平凡。