diff options
Diffstat (limited to 'OpenSim/Data/MySQL/MySQLFSAssetData.cs')
-rw-r--r-- | OpenSim/Data/MySQL/MySQLFSAssetData.cs | 379 |
1 files changed, 191 insertions, 188 deletions
diff --git a/OpenSim/Data/MySQL/MySQLFSAssetData.cs b/OpenSim/Data/MySQL/MySQLFSAssetData.cs index 19e23b5..40bfd1f 100644 --- a/OpenSim/Data/MySQL/MySQLFSAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLFSAssetData.cs | |||
@@ -41,10 +41,8 @@ namespace OpenSim.Data.MySQL | |||
41 | { | 41 | { |
42 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 42 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
43 | 43 | ||
44 | protected MySqlConnection m_Connection = null; | ||
45 | protected string m_ConnectionString; | 44 | protected string m_ConnectionString; |
46 | protected string m_Table; | 45 | protected string m_Table; |
47 | protected Object m_connLock = new Object(); | ||
48 | 46 | ||
49 | /// <summary> | 47 | /// <summary> |
50 | /// Number of days that must pass before we update the access time on an asset when it has been fetched | 48 | /// Number of days that must pass before we update the access time on an asset when it has been fetched |
@@ -75,10 +73,11 @@ namespace OpenSim.Data.MySQL | |||
75 | 73 | ||
76 | try | 74 | try |
77 | { | 75 | { |
78 | OpenDatabase(); | 76 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
79 | 77 | { | |
80 | Migration m = new Migration(m_Connection, Assembly, "FSAssetStore"); | 78 | Migration m = new Migration(conn, Assembly, "FSAssetStore"); |
81 | m.Update(); | 79 | m.Update(); |
80 | } | ||
82 | } | 81 | } |
83 | catch (MySqlException e) | 82 | catch (MySqlException e) |
84 | { | 83 | { |
@@ -100,70 +99,33 @@ namespace OpenSim.Data.MySQL | |||
100 | 99 | ||
101 | #endregion | 100 | #endregion |
102 | 101 | ||
103 | private bool OpenDatabase() | 102 | private bool ExecuteNonQuery(MySqlCommand cmd) |
104 | { | ||
105 | try | ||
106 | { | ||
107 | m_Connection = new MySqlConnection(m_ConnectionString); | ||
108 | |||
109 | m_Connection.Open(); | ||
110 | } | ||
111 | catch (MySqlException e) | ||
112 | { | ||
113 | m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", | ||
114 | e.Message.ToString()); | ||
115 | |||
116 | return false; | ||
117 | } | ||
118 | |||
119 | return true; | ||
120 | } | ||
121 | |||
122 | private IDataReader ExecuteReader(MySqlCommand c) | ||
123 | { | ||
124 | IDataReader r = null; | ||
125 | MySqlConnection connection = (MySqlConnection) ((ICloneable)m_Connection).Clone(); | ||
126 | connection.Open(); | ||
127 | c.Connection = connection; | ||
128 | |||
129 | r = c.ExecuteReader(); | ||
130 | |||
131 | return r; | ||
132 | } | ||
133 | |||
134 | private void ExecuteNonQuery(MySqlCommand c) | ||
135 | { | 103 | { |
136 | lock (m_connLock) | 104 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
137 | { | 105 | { |
138 | bool errorSeen = false; | 106 | try |
139 | |||
140 | while (true) | ||
141 | { | 107 | { |
142 | try | 108 | conn.Open(); |
143 | { | 109 | } |
144 | c.ExecuteNonQuery(); | 110 | catch (MySqlException e) |
145 | } | 111 | { |
146 | catch (MySqlException) | 112 | m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); |
147 | { | 113 | return false; |
148 | System.Threading.Thread.Sleep(500); | 114 | } |
149 | |||
150 | m_Connection.Close(); | ||
151 | m_Connection = (MySqlConnection) ((ICloneable)m_Connection).Clone(); | ||
152 | m_Connection.Open(); | ||
153 | c.Connection = m_Connection; | ||
154 | |||
155 | if (!errorSeen) | ||
156 | { | ||
157 | errorSeen = true; | ||
158 | continue; | ||
159 | } | ||
160 | m_log.ErrorFormat("[FSASSETS] MySQL command: {0}", c.CommandText); | ||
161 | throw; | ||
162 | } | ||
163 | 115 | ||
164 | break; | 116 | cmd.Connection = conn; |
117 | try | ||
118 | { | ||
119 | cmd.ExecuteNonQuery(); | ||
120 | } | ||
121 | catch (MySqlException e) | ||
122 | { | ||
123 | m_log.ErrorFormat("[FSASSETS]: Query {0} failed with {1}", cmd.CommandText, e.ToString()); | ||
124 | return false; | ||
165 | } | 125 | } |
166 | } | 126 | } |
127 | |||
128 | return true; | ||
167 | } | 129 | } |
168 | 130 | ||
169 | #region IFSAssetDataPlugin Members | 131 | #region IFSAssetDataPlugin Members |
@@ -172,63 +134,78 @@ namespace OpenSim.Data.MySQL | |||
172 | { | 134 | { |
173 | hash = String.Empty; | 135 | hash = String.Empty; |
174 | 136 | ||
175 | MySqlCommand cmd = new MySqlCommand(); | 137 | AssetMetadata meta = new AssetMetadata(); |
176 | |||
177 | cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, access_time, asset_flags from {0} where id = ?id", m_Table); | ||
178 | cmd.Parameters.AddWithValue("?id", id); | ||
179 | |||
180 | IDataReader reader = ExecuteReader(cmd); | ||
181 | 138 | ||
182 | if (!reader.Read()) | 139 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
183 | { | 140 | { |
184 | reader.Close(); | 141 | try |
185 | FreeCommand(cmd); | 142 | { |
186 | return null; | 143 | conn.Open(); |
187 | } | 144 | } |
188 | 145 | catch (MySqlException e) | |
189 | AssetMetadata meta = new AssetMetadata(); | 146 | { |
147 | m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); | ||
148 | return null; | ||
149 | } | ||
190 | 150 | ||
191 | hash = reader["hash"].ToString(); | 151 | using (MySqlCommand cmd = conn.CreateCommand()) |
152 | { | ||
153 | cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, asset_flags from {0} where id = ?id", m_Table); | ||
154 | cmd.Parameters.AddWithValue("?id", id); | ||
192 | 155 | ||
193 | meta.ID = id; | 156 | using (IDataReader reader = cmd.ExecuteReader()) |
194 | meta.FullID = new UUID(id); | 157 | { |
158 | if (!reader.Read()) | ||
159 | return null; | ||
195 | 160 | ||
196 | meta.Name = reader["name"].ToString(); | 161 | hash = reader["hash"].ToString(); |
197 | meta.Description = reader["description"].ToString(); | ||
198 | meta.Type = (sbyte)Convert.ToInt32(reader["type"]); | ||
199 | meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||
200 | meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||
201 | meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]); | ||
202 | 162 | ||
203 | int AccessTime = Convert.ToInt32(reader["access_time"]); | 163 | meta.ID = id; |
164 | meta.FullID = new UUID(id); | ||
204 | 165 | ||
205 | reader.Close(); | 166 | meta.Name = reader["name"].ToString(); |
167 | meta.Description = reader["description"].ToString(); | ||
168 | meta.Type = (sbyte)Convert.ToInt32(reader["type"]); | ||
169 | meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||
170 | meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||
171 | meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]); | ||
206 | 172 | ||
207 | UpdateAccessTime(AccessTime, cmd); | 173 | int AccessTime = Convert.ToInt32(reader["access_time"]); |
174 | UpdateAccessTime(AccessTime); | ||
175 | } | ||
176 | } | ||
208 | 177 | ||
209 | FreeCommand(cmd); | 178 | } |
210 | 179 | ||
211 | return meta; | 180 | return meta; |
212 | } | 181 | } |
213 | 182 | ||
214 | private void UpdateAccessTime(int AccessTime, MySqlCommand cmd) | 183 | private void UpdateAccessTime(int AccessTime) |
215 | { | 184 | { |
216 | // Reduce DB work by only updating access time if asset hasn't recently been accessed | 185 | // Reduce DB work by only updating access time if asset hasn't recently been accessed |
217 | // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates" | 186 | // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates" |
218 | if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates) | 187 | if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates) |
219 | return; | 188 | return; |
220 | 189 | ||
221 | cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table); | 190 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
191 | { | ||
192 | try | ||
193 | { | ||
194 | conn.Open(); | ||
195 | } | ||
196 | catch (MySqlException e) | ||
197 | { | ||
198 | m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString()); | ||
199 | return; | ||
200 | } | ||
222 | 201 | ||
223 | cmd.ExecuteNonQuery(); | 202 | using (MySqlCommand cmd = conn.CreateCommand()) |
224 | } | 203 | { |
204 | cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table); | ||
225 | 205 | ||
226 | protected void FreeCommand(MySqlCommand cmd) | 206 | cmd.ExecuteNonQuery(); |
227 | { | 207 | } |
228 | MySqlConnection c = cmd.Connection; | 208 | } |
229 | cmd.Dispose(); | ||
230 | c.Close(); | ||
231 | c.Dispose(); | ||
232 | } | 209 | } |
233 | 210 | ||
234 | public bool Store(AssetMetadata meta, string hash) | 211 | public bool Store(AssetMetadata meta, string hash) |
@@ -238,37 +215,35 @@ namespace OpenSim.Data.MySQL | |||
238 | string oldhash; | 215 | string oldhash; |
239 | AssetMetadata existingAsset = Get(meta.ID, out oldhash); | 216 | AssetMetadata existingAsset = Get(meta.ID, out oldhash); |
240 | 217 | ||
241 | MySqlCommand cmd = m_Connection.CreateCommand(); | 218 | using (MySqlCommand cmd = new MySqlCommand()) |
242 | |||
243 | cmd.Parameters.AddWithValue("?id", meta.ID); | ||
244 | cmd.Parameters.AddWithValue("?name", meta.Name); | ||
245 | cmd.Parameters.AddWithValue("?description", meta.Description); | ||
246 | cmd.Parameters.AddWithValue("?type", meta.Type.ToString()); | ||
247 | cmd.Parameters.AddWithValue("?hash", hash); | ||
248 | cmd.Parameters.AddWithValue("?asset_flags", meta.Flags); | ||
249 | |||
250 | if (existingAsset == null) | ||
251 | { | 219 | { |
252 | cmd.CommandText = String.Format("insert into {0} (id, name, description, type, hash, asset_flags, create_time, access_time) values ( ?id, ?name, ?description, ?type, ?hash, ?asset_flags, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())", m_Table); | 220 | cmd.Parameters.AddWithValue("?id", meta.ID); |
253 | 221 | cmd.Parameters.AddWithValue("?name", meta.Name); | |
254 | ExecuteNonQuery(cmd); | 222 | cmd.Parameters.AddWithValue("?description", meta.Description); |
223 | cmd.Parameters.AddWithValue("?type", meta.Type.ToString()); | ||
224 | cmd.Parameters.AddWithValue("?hash", hash); | ||
225 | cmd.Parameters.AddWithValue("?asset_flags", meta.Flags); | ||
226 | |||
227 | if (existingAsset == null) | ||
228 | { | ||
229 | cmd.CommandText = String.Format("insert into {0} (id, name, description, type, hash, asset_flags, create_time, access_time) values ( ?id, ?name, ?description, ?type, ?hash, ?asset_flags, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())", m_Table); | ||
255 | 230 | ||
256 | cmd.Dispose(); | 231 | ExecuteNonQuery(cmd); |
257 | 232 | ||
258 | return true; | 233 | return true; |
259 | } | 234 | } |
260 | 235 | ||
261 | //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table); | 236 | //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table); |
262 | 237 | ||
263 | //ExecuteNonQuery(cmd); | 238 | //ExecuteNonQuery(cmd); |
264 | 239 | ||
265 | cmd.Dispose(); | 240 | } |
266 | return false; | 241 | return false; |
267 | } | 242 | } |
268 | catch(Exception e) | 243 | catch(Exception e) |
269 | { | 244 | { |
270 | m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID); | 245 | m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID); |
271 | m_log.Error(e.ToString()); | 246 | m_log.Error(e.ToString()); |
272 | return false; | 247 | return false; |
273 | } | 248 | } |
274 | } | 249 | } |
@@ -283,26 +258,42 @@ namespace OpenSim.Data.MySQL | |||
283 | if (uuids.Length == 0) | 258 | if (uuids.Length == 0) |
284 | return new bool[0]; | 259 | return new bool[0]; |
285 | 260 | ||
261 | bool[] results = new bool[uuids.Length]; | ||
262 | for (int i = 0; i < uuids.Length; i++) | ||
263 | results[i] = false; | ||
264 | |||
286 | HashSet<UUID> exists = new HashSet<UUID>(); | 265 | HashSet<UUID> exists = new HashSet<UUID>(); |
287 | 266 | ||
288 | string ids = "'" + string.Join("','", uuids) + "'"; | 267 | string ids = "'" + string.Join("','", uuids) + "'"; |
289 | string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table); | 268 | string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table); |
290 | 269 | ||
291 | using (MySqlCommand cmd = m_Connection.CreateCommand()) | 270 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
292 | { | 271 | { |
293 | cmd.CommandText = sql; | 272 | try |
273 | { | ||
274 | conn.Open(); | ||
275 | } | ||
276 | catch (MySqlException e) | ||
277 | { | ||
278 | m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString()); | ||
279 | return results; | ||
280 | } | ||
294 | 281 | ||
295 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) | 282 | using (MySqlCommand cmd = conn.CreateCommand()) |
296 | { | 283 | { |
297 | while (dbReader.Read()) | 284 | cmd.CommandText = sql; |
285 | |||
286 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) | ||
298 | { | 287 | { |
299 | UUID id = DBGuid.FromDB(dbReader["ID"]); | 288 | while (dbReader.Read()) |
300 | exists.Add(id); | 289 | { |
290 | UUID id = DBGuid.FromDB(dbReader["ID"]); | ||
291 | exists.Add(id); | ||
292 | } | ||
301 | } | 293 | } |
302 | } | 294 | } |
303 | } | 295 | } |
304 | 296 | ||
305 | bool[] results = new bool[uuids.Length]; | ||
306 | for (int i = 0; i < uuids.Length; i++) | 297 | for (int i = 0; i < uuids.Length; i++) |
307 | results[i] = exists.Contains(uuids[i]); | 298 | results[i] = exists.Contains(uuids[i]); |
308 | return results; | 299 | return results; |
@@ -310,102 +301,114 @@ namespace OpenSim.Data.MySQL | |||
310 | 301 | ||
311 | public int Count() | 302 | public int Count() |
312 | { | 303 | { |
313 | MySqlCommand cmd = m_Connection.CreateCommand(); | 304 | int count = 0; |
314 | 305 | ||
315 | cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table); | 306 | using (MySqlConnection conn = new MySqlConnection(m_ConnectionString)) |
307 | { | ||
308 | try | ||
309 | { | ||
310 | conn.Open(); | ||
311 | } | ||
312 | catch (MySqlException e) | ||
313 | { | ||
314 | m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString()); | ||
315 | return 0; | ||
316 | } | ||
316 | 317 | ||
317 | IDataReader reader = ExecuteReader(cmd); | 318 | MySqlCommand cmd = conn.CreateCommand(); |
318 | 319 | ||
319 | reader.Read(); | 320 | cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table); |
320 | 321 | ||
321 | int count = Convert.ToInt32(reader["count"]); | 322 | using (IDataReader reader = cmd.ExecuteReader()) |
323 | { | ||
324 | reader.Read(); | ||
322 | 325 | ||
323 | reader.Close(); | 326 | count = Convert.ToInt32(reader["count"]); |
324 | FreeCommand(cmd); | 327 | } |
328 | } | ||
325 | 329 | ||
326 | return count; | 330 | return count; |
327 | } | 331 | } |
328 | 332 | ||
329 | public bool Delete(string id) | 333 | public bool Delete(string id) |
330 | { | 334 | { |
331 | using (MySqlCommand cmd = m_Connection.CreateCommand()) | 335 | MySqlCommand cmd = new MySqlCommand(); |
332 | { | ||
333 | cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table); | ||
334 | 336 | ||
335 | cmd.Parameters.AddWithValue("?id", id); | 337 | cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table); |
336 | 338 | ||
337 | ExecuteNonQuery(cmd); | 339 | cmd.Parameters.AddWithValue("?id", id); |
338 | } | 340 | |
341 | ExecuteNonQuery(cmd); | ||
342 | |||
343 | cmd.Dispose(); | ||
339 | 344 | ||
340 | return true; | 345 | return true; |
341 | } | 346 | } |
342 | 347 | ||
343 | public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store) | 348 | public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store) |
344 | { | 349 | { |
345 | MySqlConnection importConn; | 350 | int imported = 0; |
346 | |||
347 | try | ||
348 | { | ||
349 | importConn = new MySqlConnection(conn); | ||
350 | 351 | ||
351 | importConn.Open(); | 352 | using (MySqlConnection importConn = new MySqlConnection(conn)) |
352 | } | ||
353 | catch (MySqlException e) | ||
354 | { | 353 | { |
355 | m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", | 354 | try |
356 | e.Message.ToString()); | 355 | { |
356 | importConn.Open(); | ||
357 | } | ||
358 | catch (MySqlException e) | ||
359 | { | ||
360 | m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", | ||
361 | e.Message.ToString()); | ||
357 | 362 | ||
358 | return; | 363 | return; |
359 | } | 364 | } |
360 | 365 | ||
361 | int imported = 0; | 366 | using (MySqlCommand cmd = importConn.CreateCommand()) |
367 | { | ||
368 | string limit = String.Empty; | ||
369 | if (count != -1) | ||
370 | { | ||
371 | limit = String.Format(" limit {0},{1}", start, count); | ||
372 | } | ||
362 | 373 | ||
363 | MySqlCommand cmd = importConn.CreateCommand(); | 374 | cmd.CommandText = String.Format("select * from {0}{1}", table, limit); |
364 | 375 | ||
365 | string limit = String.Empty; | 376 | MainConsole.Instance.Output("Querying database"); |
366 | if (count != -1) | 377 | using (IDataReader reader = cmd.ExecuteReader()) |
367 | { | 378 | { |
368 | limit = String.Format(" limit {0},{1}", start, count); | 379 | MainConsole.Instance.Output("Reading data"); |
369 | } | ||
370 | |||
371 | cmd.CommandText = String.Format("select * from {0}{1}", table, limit); | ||
372 | 380 | ||
373 | MainConsole.Instance.Output("Querying database"); | 381 | while (reader.Read()) |
374 | IDataReader reader = cmd.ExecuteReader(); | 382 | { |
383 | if ((imported % 100) == 0) | ||
384 | { | ||
385 | MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported)); | ||
386 | } | ||
375 | 387 | ||
376 | MainConsole.Instance.Output("Reading data"); | 388 | AssetBase asset = new AssetBase(); |
389 | AssetMetadata meta = new AssetMetadata(); | ||
377 | 390 | ||
378 | while (reader.Read()) | 391 | meta.ID = reader["id"].ToString(); |
379 | { | 392 | meta.FullID = new UUID(meta.ID); |
380 | if ((imported % 100) == 0) | ||
381 | { | ||
382 | MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported)); | ||
383 | } | ||
384 | |||
385 | AssetBase asset = new AssetBase(); | ||
386 | AssetMetadata meta = new AssetMetadata(); | ||
387 | 393 | ||
388 | meta.ID = reader["id"].ToString(); | 394 | meta.Name = reader["name"].ToString(); |
389 | meta.FullID = new UUID(meta.ID); | 395 | meta.Description = reader["description"].ToString(); |
396 | meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]); | ||
397 | meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||
398 | meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||
390 | 399 | ||
391 | meta.Name = reader["name"].ToString(); | 400 | asset.Metadata = meta; |
392 | meta.Description = reader["description"].ToString(); | 401 | asset.Data = (byte[])reader["data"]; |
393 | meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]); | ||
394 | meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type); | ||
395 | meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"])); | ||
396 | 402 | ||
397 | asset.Metadata = meta; | 403 | store(asset, force); |
398 | asset.Data = (byte[])reader["data"]; | ||
399 | 404 | ||
400 | store(asset, force); | 405 | imported++; |
406 | } | ||
407 | } | ||
401 | 408 | ||
402 | imported++; | 409 | } |
403 | } | 410 | } |
404 | 411 | ||
405 | reader.Close(); | ||
406 | cmd.Dispose(); | ||
407 | importConn.Close(); | ||
408 | |||
409 | MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported)); | 412 | MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported)); |
410 | } | 413 | } |
411 | 414 | ||