aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL
diff options
context:
space:
mode:
authorMelanie Thielker2008-11-30 05:20:19 +0000
committerMelanie Thielker2008-11-30 05:20:19 +0000
commit38380def178150d66a307702bcc4484f21934bba (patch)
tree38316acc87b60205916a4fabe19162ef91cc254e /OpenSim/Data/MySQL
parentRevert r7548 and r7549 until someone with prebuild-fu can help structure the ... (diff)
downloadopensim-SC_OLD-38380def178150d66a307702bcc4484f21934bba.zip
opensim-SC_OLD-38380def178150d66a307702bcc4484f21934bba.tar.gz
opensim-SC_OLD-38380def178150d66a307702bcc4484f21934bba.tar.bz2
opensim-SC_OLD-38380def178150d66a307702bcc4484f21934bba.tar.xz
More changes to the MySQL adapter. take advantage of pooling and run lock-free.
This should finally kill the "There is already an open data reader associated with this connection, which must be closed first" error that makes people's builds not save
Diffstat (limited to 'OpenSim/Data/MySQL')
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs979
1 files changed, 472 insertions, 507 deletions
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 33e005b..3fb0a8a 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -72,69 +72,10 @@ namespace OpenSim.Data.MySQL
72 cmd.CommandText = "delete from prims, primshapes using prims " + 72 cmd.CommandText = "delete from prims, primshapes using prims " +
73 "left join primshapes on prims.uuid = primshapes.uuid " + 73 "left join primshapes on prims.uuid = primshapes.uuid " +
74 "where PCode = 9 and State <> 0"; 74 "where PCode = 9 and State <> 0";
75 ExecuteNonQuery(cmd); 75 cmd.ExecuteNonQuery();
76 cmd.Dispose(); 76 cmd.Dispose();
77 }
78
79 private IDataReader ExecuteReader(MySqlCommand c)
80 {
81 IDataReader r = null;
82 bool errorSeen = false;
83
84 while (true)
85 {
86 try
87 {
88 r = c.ExecuteReader();
89 }
90 catch (MySqlException)
91 {
92 System.Threading.Thread.Sleep(500);
93
94 m_Connection.Close();
95 m_Connection.Open();
96
97 if (!errorSeen)
98 {
99 errorSeen = true;
100 continue;
101 }
102 throw;
103 }
104
105 break;
106 }
107
108 return r;
109 }
110
111 private void ExecuteNonQuery(MySqlCommand c)
112 {
113 bool errorSeen = false;
114
115 while (true)
116 {
117 try
118 {
119 c.ExecuteNonQuery();
120 }
121 catch (MySqlException)
122 {
123 System.Threading.Thread.Sleep(500);
124
125 m_Connection.Close();
126 m_Connection.Open();
127 77
128 if (!errorSeen) 78 m_Connection.Close();
129 {
130 errorSeen = true;
131 continue;
132 }
133 throw;
134 }
135
136 break;
137 }
138 } 79 }
139 80
140 public void Dispose() {} 81 public void Dispose() {}
@@ -150,115 +91,116 @@ namespace OpenSim.Data.MySQL
150 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) 91 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
151 return; 92 return;
152 93
153 lock (m_Connection) 94 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
95 c.Open();
96
97 MySqlCommand cmd = c.CreateCommand();
98
99 foreach (SceneObjectPart prim in obj.Children.Values)
154 { 100 {
155 MySqlCommand cmd = m_Connection.CreateCommand(); 101 cmd.Parameters.Clear();
156 102
157 foreach (SceneObjectPart prim in obj.Children.Values) 103 cmd.CommandText = "replace into prims ("+
158 { 104 "UUID, ParentID, CreationDate, "+
159 cmd.Parameters.Clear(); 105 "Name, Text, Description, "+
160 106 "SitName, TouchName, ObjectFlags, "+
161 cmd.CommandText = "replace into prims ("+ 107 "OwnerMask, NextOwnerMask, GroupMask, "+
162 "UUID, ParentID, CreationDate, "+ 108 "EveryoneMask, BaseMask, PositionX, "+
163 "Name, Text, Description, "+ 109 "PositionY, PositionZ, GroupPositionX, "+
164 "SitName, TouchName, ObjectFlags, "+ 110 "GroupPositionY, GroupPositionZ, VelocityX, "+
165 "OwnerMask, NextOwnerMask, GroupMask, "+ 111 "VelocityY, VelocityZ, AngularVelocityX, "+
166 "EveryoneMask, BaseMask, PositionX, "+ 112 "AngularVelocityY, AngularVelocityZ, "+
167 "PositionY, PositionZ, GroupPositionX, "+ 113 "AccelerationX, AccelerationY, "+
168 "GroupPositionY, GroupPositionZ, VelocityX, "+ 114 "AccelerationZ, RotationX, "+
169 "VelocityY, VelocityZ, AngularVelocityX, "+ 115 "RotationY, RotationZ, "+
170 "AngularVelocityY, AngularVelocityZ, "+ 116 "RotationW, SitTargetOffsetX, "+
171 "AccelerationX, AccelerationY, "+ 117 "SitTargetOffsetY, SitTargetOffsetZ, "+
172 "AccelerationZ, RotationX, "+ 118 "SitTargetOrientW, SitTargetOrientX, "+
173 "RotationY, RotationZ, "+ 119 "SitTargetOrientY, SitTargetOrientZ, "+
174 "RotationW, SitTargetOffsetX, "+ 120 "RegionUUID, CreatorID, "+
175 "SitTargetOffsetY, SitTargetOffsetZ, "+ 121 "OwnerID, GroupID, "+
176 "SitTargetOrientW, SitTargetOrientX, "+ 122 "LastOwnerID, SceneGroupID, "+
177 "SitTargetOrientY, SitTargetOrientZ, "+ 123 "PayPrice, PayButton1, "+
178 "RegionUUID, CreatorID, "+ 124 "PayButton2, PayButton3, "+
179 "OwnerID, GroupID, "+ 125 "PayButton4, LoopedSound, "+
180 "LastOwnerID, SceneGroupID, "+ 126 "LoopedSoundGain, TextureAnimation, "+
181 "PayPrice, PayButton1, "+ 127 "OmegaX, OmegaY, OmegaZ, "+
182 "PayButton2, PayButton3, "+ 128 "CameraEyeOffsetX, CameraEyeOffsetY, "+
183 "PayButton4, LoopedSound, "+ 129 "CameraEyeOffsetZ, CameraAtOffsetX, "+
184 "LoopedSoundGain, TextureAnimation, "+ 130 "CameraAtOffsetY, CameraAtOffsetZ, "+
185 "OmegaX, OmegaY, OmegaZ, "+ 131 "ForceMouselook, ScriptAccessPin, "+
186 "CameraEyeOffsetX, CameraEyeOffsetY, "+ 132 "AllowedDrop, DieAtEdge, "+
187 "CameraEyeOffsetZ, CameraAtOffsetX, "+ 133 "SalePrice, SaleType, "+
188 "CameraAtOffsetY, CameraAtOffsetZ, "+ 134 "ColorR, ColorG, ColorB, ColorA, "+
189 "ForceMouselook, ScriptAccessPin, "+ 135 "ParticleSystem, ClickAction, Material, "+
190 "AllowedDrop, DieAtEdge, "+ 136 "CollisionSound, CollisionSoundVolume, "+
191 "SalePrice, SaleType, "+ 137 "LinkNumber) values (" + "?UUID, ?ParentID, "+
192 "ColorR, ColorG, ColorB, ColorA, "+ 138 "?CreationDate, ?Name, ?Text, "+
193 "ParticleSystem, ClickAction, Material, "+ 139 "?Description, ?SitName, ?TouchName, "+
194 "CollisionSound, CollisionSoundVolume, "+ 140 "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+
195 "LinkNumber) values (" + "?UUID, ?ParentID, "+ 141 "?GroupMask, ?EveryoneMask, ?BaseMask, "+
196 "?CreationDate, ?Name, ?Text, "+ 142 "?PositionX, ?PositionY, ?PositionZ, "+
197 "?Description, ?SitName, ?TouchName, "+ 143 "?GroupPositionX, ?GroupPositionY, "+
198 "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+ 144 "?GroupPositionZ, ?VelocityX, "+
199 "?GroupMask, ?EveryoneMask, ?BaseMask, "+ 145 "?VelocityY, ?VelocityZ, ?AngularVelocityX, "+
200 "?PositionX, ?PositionY, ?PositionZ, "+ 146 "?AngularVelocityY, ?AngularVelocityZ, "+
201 "?GroupPositionX, ?GroupPositionY, "+ 147 "?AccelerationX, ?AccelerationY, "+
202 "?GroupPositionZ, ?VelocityX, "+ 148 "?AccelerationZ, ?RotationX, "+
203 "?VelocityY, ?VelocityZ, ?AngularVelocityX, "+ 149 "?RotationY, ?RotationZ, "+
204 "?AngularVelocityY, ?AngularVelocityZ, "+ 150 "?RotationW, ?SitTargetOffsetX, "+
205 "?AccelerationX, ?AccelerationY, "+ 151 "?SitTargetOffsetY, ?SitTargetOffsetZ, "+
206 "?AccelerationZ, ?RotationX, "+ 152 "?SitTargetOrientW, ?SitTargetOrientX, "+
207 "?RotationY, ?RotationZ, "+ 153 "?SitTargetOrientY, ?SitTargetOrientZ, "+
208 "?RotationW, ?SitTargetOffsetX, "+ 154 "?RegionUUID, ?CreatorID, ?OwnerID, "+
209 "?SitTargetOffsetY, ?SitTargetOffsetZ, "+ 155 "?GroupID, ?LastOwnerID, ?SceneGroupID, "+
210 "?SitTargetOrientW, ?SitTargetOrientX, "+ 156 "?PayPrice, ?PayButton1, ?PayButton2, "+
211 "?SitTargetOrientY, ?SitTargetOrientZ, "+ 157 "?PayButton3, ?PayButton4, ?LoopedSound, "+
212 "?RegionUUID, ?CreatorID, ?OwnerID, "+ 158 "?LoopedSoundGain, ?TextureAnimation, "+
213 "?GroupID, ?LastOwnerID, ?SceneGroupID, "+ 159 "?OmegaX, ?OmegaY, ?OmegaZ, "+
214 "?PayPrice, ?PayButton1, ?PayButton2, "+ 160 "?CameraEyeOffsetX, ?CameraEyeOffsetY, "+
215 "?PayButton3, ?PayButton4, ?LoopedSound, "+ 161 "?CameraEyeOffsetZ, ?CameraAtOffsetX, "+
216 "?LoopedSoundGain, ?TextureAnimation, "+ 162 "?CameraAtOffsetY, ?CameraAtOffsetZ, "+
217 "?OmegaX, ?OmegaY, ?OmegaZ, "+ 163 "?ForceMouselook, ?ScriptAccessPin, "+
218 "?CameraEyeOffsetX, ?CameraEyeOffsetY, "+ 164 "?AllowedDrop, ?DieAtEdge, ?SalePrice, "+
219 "?CameraEyeOffsetZ, ?CameraAtOffsetX, "+ 165 "?SaleType, ?ColorR, ?ColorG, "+
220 "?CameraAtOffsetY, ?CameraAtOffsetZ, "+ 166 "?ColorB, ?ColorA, ?ParticleSystem, "+
221 "?ForceMouselook, ?ScriptAccessPin, "+ 167 "?ClickAction, ?Material, ?CollisionSound, "+
222 "?AllowedDrop, ?DieAtEdge, ?SalePrice, "+ 168 "?CollisionSoundVolume, ?LinkNumber)";
223 "?SaleType, ?ColorR, ?ColorG, "+ 169
224 "?ColorB, ?ColorA, ?ParticleSystem, "+ 170 FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
225 "?ClickAction, ?Material, ?CollisionSound, "+ 171
226 "?CollisionSoundVolume, ?LinkNumber)"; 172 cmd.ExecuteNonQuery();
227 173
228 FillPrimCommand(cmd, prim, obj.UUID, regionUUID); 174 cmd.Parameters.Clear();
229 175
230 ExecuteNonQuery(cmd); 176 cmd.CommandText = "replace into primshapes ("+
231 177 "UUID, Shape, ScaleX, ScaleY, "+
232 cmd.Parameters.Clear(); 178 "ScaleZ, PCode, PathBegin, PathEnd, "+
233 179 "PathScaleX, PathScaleY, PathShearX, "+
234 cmd.CommandText = "replace into primshapes ("+ 180 "PathShearY, PathSkew, PathCurve, "+
235 "UUID, Shape, ScaleX, ScaleY, "+ 181 "PathRadiusOffset, PathRevolutions, "+
236 "ScaleZ, PCode, PathBegin, PathEnd, "+ 182 "PathTaperX, PathTaperY, PathTwist, "+
237 "PathScaleX, PathScaleY, PathShearX, "+ 183 "PathTwistBegin, ProfileBegin, ProfileEnd, "+
238 "PathShearY, PathSkew, PathCurve, "+ 184 "ProfileCurve, ProfileHollow, Texture, "+
239 "PathRadiusOffset, PathRevolutions, "+ 185 "ExtraParams, State) values (?UUID, "+
240 "PathTaperX, PathTaperY, PathTwist, "+ 186 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+
241 "PathTwistBegin, ProfileBegin, ProfileEnd, "+ 187 "?PCode, ?PathBegin, ?PathEnd, "+
242 "ProfileCurve, ProfileHollow, Texture, "+ 188 "?PathScaleX, ?PathScaleY, "+
243 "ExtraParams, State) values (?UUID, "+ 189 "?PathShearX, ?PathShearY, "+
244 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+ 190 "?PathSkew, ?PathCurve, ?PathRadiusOffset, "+
245 "?PCode, ?PathBegin, ?PathEnd, "+ 191 "?PathRevolutions, ?PathTaperX, "+
246 "?PathScaleX, ?PathScaleY, "+ 192 "?PathTaperY, ?PathTwist, "+
247 "?PathShearX, ?PathShearY, "+ 193 "?PathTwistBegin, ?ProfileBegin, "+
248 "?PathSkew, ?PathCurve, ?PathRadiusOffset, "+ 194 "?ProfileEnd, ?ProfileCurve, "+
249 "?PathRevolutions, ?PathTaperX, "+ 195 "?ProfileHollow, ?Texture, ?ExtraParams, "+
250 "?PathTaperY, ?PathTwist, "+ 196 "?State)";
251 "?PathTwistBegin, ?ProfileBegin, "+ 197
252 "?ProfileEnd, ?ProfileCurve, "+ 198 FillShapeCommand(cmd, prim);
253 "?ProfileHollow, ?Texture, ?ExtraParams, "+ 199
254 "?State)"; 200 cmd.ExecuteNonQuery();
255
256 FillShapeCommand(cmd, prim);
257
258 ExecuteNonQuery(cmd);
259 }
260 cmd.Dispose();
261 } 201 }
202 cmd.Dispose();
203 c.Close();
262 } 204 }
263 205
264 public void RemoveObject(UUID obj, UUID regionUUID) 206 public void RemoveObject(UUID obj, UUID regionUUID)
@@ -271,43 +213,51 @@ namespace OpenSim.Data.MySQL
271 // cause the loss of a prim, but is cleaner. 213 // cause the loss of a prim, but is cleaner.
272 // It's also faster because it uses the primary key. 214 // It's also faster because it uses the primary key.
273 // 215 //
274 lock (m_Connection) 216 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
275 { 217 c.Open();
276 MySqlCommand cmd = m_Connection.CreateCommand();
277 218
278 cmd.CommandText = "select UUID from prims where "+ 219 MySqlCommand cmd = c.CreateCommand();
279 "SceneGroupID= ?UUID";
280 220
281 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(obj)); 221 cmd.CommandText = "select UUID from prims where "+
222 "SceneGroupID= ?UUID";
282 223
283 List<UUID> uuids = new List<UUID>(); 224 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(obj));
284 225
285 IDataReader reader = ExecuteReader(cmd); 226 List<UUID> uuids = new List<UUID>();
286 227
287 try 228 IDataReader reader = cmd.ExecuteReader();
288 { 229
289 while (reader.Read()) 230 try
290 { 231 {
291 uuids.Add(new UUID(reader["UUID"].ToString())); 232 while(reader.Read())
292 }
293 }
294 finally
295 { 233 {
296 reader.Close(); 234 uuids.Add(new UUID(reader["UUID"].ToString()));
297 } 235 }
236 }
237 finally
238 {
239 reader.Close();
240 }
298 241
299 foreach (UUID uuid in uuids) 242 cmd.CommandText = "delete from prims where SceneGroupID= ?UUID";
300 RemoveItems(uuid);
301 243
302 cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; 244 cmd.ExecuteNonQuery();
303 245
304 ExecuteNonQuery(cmd); 246 cmd.CommandText = "delete from primshapes where UUID = ?UUID";
305 247
306 cmd.CommandText = "delete from primshapes where UUID = ?UUID"; 248 foreach (UUID uuid in uuids)
249 {
250 cmd.Parameters.Clear();
251 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(uuid));
307 252
308 ExecuteNonQuery(cmd); 253 cmd.ExecuteNonQuery();
309 cmd.Dispose();
310 } 254 }
255
256 cmd.Dispose();
257 c.Close();
258
259 foreach (UUID uuid in uuids)
260 RemoveItems(uuid);
311 } 261 }
312 262
313 /// <summary> 263 /// <summary>
@@ -317,18 +267,19 @@ namespace OpenSim.Data.MySQL
317 /// <param name="uuid">the Item UUID</param> 267 /// <param name="uuid">the Item UUID</param>
318 private void RemoveItems(UUID uuid) 268 private void RemoveItems(UUID uuid)
319 { 269 {
320 lock (m_Connection) 270 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
321 { 271 c.Open();
322 MySqlCommand cmd = m_Connection.CreateCommand();
323 272
324 cmd.CommandText = "delete from primitems where " + 273 MySqlCommand cmd = c.CreateCommand();
325 "PrimID = ?PrimID";
326 274
327 cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); 275 cmd.CommandText = "delete from primitems where " +
276 "PrimID = ?PrimID";
328 277
329 ExecuteNonQuery(cmd); 278 cmd.Parameters.AddWithValue("PrimID", uuid.ToString());
330 cmd.Dispose(); 279
331 } 280 cmd.ExecuteNonQuery();
281 cmd.Dispose();
282 c.Close();
332 } 283 }
333 284
334 public List<SceneObjectGroup> LoadObjects(UUID regionUUID) 285 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
@@ -338,71 +289,72 @@ namespace OpenSim.Data.MySQL
338 List<SceneObjectPart> prims = new List<SceneObjectPart>(); 289 List<SceneObjectPart> prims = new List<SceneObjectPart>();
339 SceneObjectGroup grp = null; 290 SceneObjectGroup grp = null;
340 291
341 lock (m_Connection) 292 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
342 { 293 c.Open();
343 MySqlCommand cmd = m_Connection.CreateCommand();
344 294
345 cmd.CommandText = "select *, " + 295 MySqlCommand cmd = c.CreateCommand();
346 "case when prims.UUID = SceneGroupID " +
347 "then 0 else 1 end as sort from prims " +
348 "left join primshapes on prims.UUID = primshapes.UUID "+
349 "where RegionUUID = ?RegionUUID " +
350 "order by SceneGroupID asc, sort asc, LinkNumber asc";
351
352 cmd.Parameters.AddWithValue("RegionUUID",
353 Util.ToRawUuidString(regionUUID));
354 296
355 IDataReader reader = ExecuteReader(cmd); 297 cmd.CommandText = "select *, " +
298 "case when prims.UUID = SceneGroupID " +
299 "then 0 else 1 end as sort from prims " +
300 "left join primshapes on prims.UUID = primshapes.UUID "+
301 "where RegionUUID = ?RegionUUID " +
302 "order by SceneGroupID asc, sort asc, LinkNumber asc";
303
304 cmd.Parameters.AddWithValue("RegionUUID",
305 Util.ToRawUuidString(regionUUID));
356 306
357 try 307 IDataReader reader = cmd.ExecuteReader();
308
309 try
310 {
311 while (reader.Read())
358 { 312 {
359 while (reader.Read()) 313 SceneObjectPart prim = BuildPrim(reader);
360 { 314 if (reader["Shape"] is DBNull)
361 SceneObjectPart prim = BuildPrim(reader); 315 prim.Shape = PrimitiveBaseShape.Default;
362 if (reader["Shape"] is DBNull) 316 else
363 prim.Shape = PrimitiveBaseShape.Default; 317 prim.Shape = BuildShape(reader);
364 else
365 prim.Shape = BuildShape(reader);
366 318
367 prim.FolderID = prim.UUID; // A relic from when we 319 prim.FolderID = prim.UUID; // A relic from when we
368 // we thought prims contained 320 // we thought prims contained
369 // folder objects. In 321 // folder objects. In
370 // reality, prim == folder 322 // reality, prim == folder
371 prims.Add(prim); 323 prims.Add(prim);
372 324
373 UUID groupID = new UUID(reader["SceneGroupID"].ToString()); 325 UUID groupID = new UUID(reader["SceneGroupID"].ToString());
374 326
375 if (groupID != lastGroupID) // New SOG 327 if (groupID != lastGroupID) // New SOG
376 { 328 {
377 if (grp != null) 329 if (grp != null)
378 objects.Add(grp); 330 objects.Add(grp);
379 331
380 lastGroupID = groupID; 332 lastGroupID = groupID;
381 333
382 grp = new SceneObjectGroup(prim); 334 grp = new SceneObjectGroup(prim);
383 } 335 }
384 else 336 else
385 { 337 {
386 // Black magic to preserve link numbers 338 // Black magic to preserve link numbers
387 // 339 //
388 int link = prim.LinkNum; 340 int link = prim.LinkNum;
389 341
390 grp.AddPart(prim); 342 grp.AddPart(prim);
391 343
392 if (link != 0) 344 if (link != 0)
393 prim.LinkNum = link; 345 prim.LinkNum = link;
394 }
395 } 346 }
396 } 347 }
397 finally
398 {
399 reader.Close();
400 }
401
402 if (grp != null)
403 objects.Add(grp);
404 cmd.Dispose();
405 } 348 }
349 finally
350 {
351 reader.Close();
352 }
353
354 if (grp != null)
355 objects.Add(grp);
356 cmd.Dispose();
357 c.Close();
406 358
407 foreach (SceneObjectPart part in prims) 359 foreach (SceneObjectPart part in prims)
408 LoadItems(part); 360 LoadItems(part);
@@ -418,65 +370,67 @@ namespace OpenSim.Data.MySQL
418 /// <param name="prim">The prim</param> 370 /// <param name="prim">The prim</param>
419 private void LoadItems(SceneObjectPart prim) 371 private void LoadItems(SceneObjectPart prim)
420 { 372 {
421 lock (m_Connection) 373 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
422 { 374 c.Open();
423 MySqlCommand cmd = m_Connection.CreateCommand();
424 375
425 cmd.CommandText = "select * from primitems where "+ 376 MySqlCommand cmd = c.CreateCommand();
426 "PrimID = ?PrimID";
427 377
428 cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); 378 cmd.CommandText = "select * from primitems where "+
379 "PrimID = ?PrimID";
429 380
430 IDataReader reader = ExecuteReader(cmd); 381 cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString());
431 List<TaskInventoryItem> inventory =
432 new List<TaskInventoryItem>();
433 382
434 try 383 IDataReader reader = cmd.ExecuteReader();
435 { 384 List<TaskInventoryItem> inventory =
436 while (reader.Read()) 385 new List<TaskInventoryItem>();
437 {
438 TaskInventoryItem item = BuildItem(reader);
439 386
440 item.ParentID = prim.UUID; // Values in database are 387 try
441 // often wrong 388 {
442 inventory.Add(item); 389 while (reader.Read())
443 }
444 }
445 finally
446 { 390 {
447 reader.Close(); 391 TaskInventoryItem item = BuildItem(reader);
448 }
449 392
450 cmd.Dispose(); 393 item.ParentID = prim.UUID; // Values in database are
451 prim.Inventory.RestoreInventoryItems(inventory); 394 // often wrong
395 inventory.Add(item);
396 }
452 } 397 }
398 finally
399 {
400 reader.Close();
401 }
402
403 cmd.Dispose();
404 c.Close();
405 prim.Inventory.RestoreInventoryItems(inventory);
453 } 406 }
454 407
455 public void StoreTerrain(double[,] ter, UUID regionID) 408 public void StoreTerrain(double[,] ter, UUID regionID)
456 { 409 {
457 m_log.Info("[REGION DB]: Storing terrain"); 410 m_log.Info("[REGION DB]: Storing terrain");
458 411
459 lock (m_Connection) 412 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
460 { 413 c.Open();
461 MySqlCommand cmd = m_Connection.CreateCommand(); 414
462 415 MySqlCommand cmd = c.CreateCommand();
463 cmd.CommandText = "delete from terrain where " + 416
464 "RegionUUID = ?RegionUUID"; 417 cmd.CommandText = "delete from terrain where " +
465 cmd.Parameters.AddWithValue("RegionUUID", 418 "RegionUUID = ?RegionUUID";
466 Util.ToRawUuidString(regionID)); 419 cmd.Parameters.AddWithValue("RegionUUID",
467 420 Util.ToRawUuidString(regionID));
468 ExecuteNonQuery(cmd); 421
469 422 cmd.ExecuteNonQuery();
470 cmd.CommandText = "insert into terrain (RegionUUID, " + 423
471 "Revision, Heightfield) values (?RegionUUID, " + 424 cmd.CommandText = "insert into terrain (RegionUUID, " +
472 "1, ?Heightfield)"; 425 "Revision, Heightfield) values (?RegionUUID, " +
473 426 "1, ?Heightfield)";
474 cmd.Parameters.AddWithValue("Heightfield", 427
475 SerializeTerrain(ter)); 428 cmd.Parameters.AddWithValue("Heightfield",
476 429 SerializeTerrain(ter));
477 ExecuteNonQuery(cmd); 430
478 cmd.Dispose(); 431 cmd.ExecuteNonQuery();
479 } 432 cmd.Dispose();
433 c.Close();
480 } 434 }
481 435
482 public double[,] LoadTerrain(UUID regionID) 436 public double[,] LoadTerrain(UUID regionID)
@@ -484,254 +438,264 @@ namespace OpenSim.Data.MySQL
484 double[,] terrain = new double[256,256]; 438 double[,] terrain = new double[256,256];
485 terrain.Initialize(); 439 terrain.Initialize();
486 440
487 lock (m_Connection) 441 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
488 { 442 c.Open();
489 MySqlCommand cmd = m_Connection.CreateCommand();
490 cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
491 "from terrain where RegionUUID = ?RegionUUID "+
492 "order by Revision desc limit 1";
493 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
494 443
495 IDataReader reader = ExecuteReader(cmd); 444 MySqlCommand cmd = c.CreateCommand();
496 445
497 try 446 cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
447 "from terrain where RegionUUID = ?RegionUUID "+
448 "order by Revision desc limit 1";
449 cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
450
451 IDataReader reader = cmd.ExecuteReader();
452
453 try
454 {
455 while (reader.Read())
498 { 456 {
499 while (reader.Read()) 457 MemoryStream mstr = new MemoryStream((byte[]) reader["Heightfield"]);
500 { 458 int rev = 0;
501 MemoryStream mstr = new MemoryStream((byte[]) reader["Heightfield"]);
502 int rev = 0;
503 459
504 BinaryReader br = new BinaryReader(mstr); 460 BinaryReader br = new BinaryReader(mstr);
505 for (int x = 0; x < 256; x++) 461 for (int x = 0; x < 256; x++)
462 {
463 for (int y = 0; y < 256; y++)
506 { 464 {
507 for (int y = 0; y < 256; y++) 465 terrain[x, y] = br.ReadDouble();
508 {
509 terrain[x, y] = br.ReadDouble();
510 }
511 rev = Convert.ToInt32(reader["Revision"]);
512 } 466 }
513 m_log.InfoFormat("[REGION DB]: Loaded terrain " + 467 rev = Convert.ToInt32(reader["Revision"]);
514 "revision r{0}", rev);
515
516 return terrain;
517 } 468 }
518 } 469 m_log.InfoFormat("[REGION DB]: Loaded terrain " +
519 finally 470 "revision r{0}", rev);
520 { 471
521 reader.Close(); 472 reader.Close();
473 cmd.Dispose();
474 c.Close();
475 return terrain;
522 } 476 }
523 cmd.Dispose();
524 } 477 }
478 catch (Exception)
479 {
480 }
481 reader.Close();
482 cmd.Dispose();
483 c.Close();
525 484
526 return null; 485 return null;
527 } 486 }
528 487
529 public void RemoveLandObject(UUID globalID) 488 public void RemoveLandObject(UUID globalID)
530 { 489 {
531 lock (m_Connection) 490 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
532 { 491 c.Open();
533 MySqlCommand cmd = m_Connection.CreateCommand();
534 492
535 cmd.CommandText = "delete from land where UUID = ?UUID"; 493 MySqlCommand cmd = c.CreateCommand();
536 494
537 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID)); 495 cmd.CommandText = "delete from land where UUID = ?UUID";
538 496
539 ExecuteNonQuery(cmd); 497 cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID));
540 cmd.Dispose(); 498
541 } 499 cmd.ExecuteNonQuery();
500 cmd.Dispose();
501 c.Close();
542 } 502 }
543 503
544 public void StoreLandObject(ILandObject parcel) 504 public void StoreLandObject(ILandObject parcel)
545 { 505 {
546 lock (m_Connection) 506 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
507 c.Open();
508
509 MySqlCommand cmd = c.CreateCommand();
510
511 cmd.CommandText = "replace into land (UUID, RegionUUID, " +
512 "LocalLandID, Bitmap, Name, Description, " +
513 "OwnerUUID, IsGroupOwned, Area, AuctionID, " +
514 "Category, ClaimDate, ClaimPrice, GroupUUID, " +
515 "SalePrice, LandStatus, LandFlags, LandingType, " +
516 "MediaAutoScale, MediaTextureUUID, MediaURL, " +
517 "MusicURL, PassHours, PassPrice, SnapshotUUID, " +
518 "UserLocationX, UserLocationY, UserLocationZ, " +
519 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
520 "AuthbuyerID, OtherCleanTime, Dwell) values (" +
521 "?UUID, ?RegionUUID, " +
522 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
523 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
524 "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " +
525 "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " +
526 "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " +
527 "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
528 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
529 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
530 "?AuthbuyerID, ?OtherCleanTime, ?Dwell)";
531
532 FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
533
534 cmd.ExecuteNonQuery();
535
536 cmd.CommandText = "delete from landaccesslist where " +
537 "LandUUID = ?UUID";
538
539 cmd.ExecuteNonQuery();
540
541 cmd.Parameters.Clear();
542 cmd.CommandText = "insert into landaccesslist (LandUUID, " +
543 "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " +
544 "?Flags)";
545
546 foreach (ParcelManager.ParcelAccessEntry entry in
547 parcel.landData.ParcelAccessList)
547 { 548 {
548 MySqlCommand cmd = m_Connection.CreateCommand(); 549 FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
549 550 cmd.ExecuteNonQuery();
550 cmd.CommandText = "replace into land (UUID, RegionUUID, " +
551 "LocalLandID, Bitmap, Name, Description, " +
552 "OwnerUUID, IsGroupOwned, Area, AuctionID, " +
553 "Category, ClaimDate, ClaimPrice, GroupUUID, " +
554 "SalePrice, LandStatus, LandFlags, LandingType, " +
555 "MediaAutoScale, MediaTextureUUID, MediaURL, " +
556 "MusicURL, PassHours, PassPrice, SnapshotUUID, " +
557 "UserLocationX, UserLocationY, UserLocationZ, " +
558 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
559 "AuthbuyerID, OtherCleanTime, Dwell) values (" +
560 "?UUID, ?RegionUUID, " +
561 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
562 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
563 "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " +
564 "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " +
565 "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " +
566 "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " +
567 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
568 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
569 "?AuthbuyerID, ?OtherCleanTime, ?Dwell)";
570
571 FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
572
573 ExecuteNonQuery(cmd);
574
575 cmd.CommandText = "delete from landaccesslist where " +
576 "LandUUID = ?UUID";
577
578 ExecuteNonQuery(cmd);
579
580 cmd.Parameters.Clear(); 551 cmd.Parameters.Clear();
581 cmd.CommandText = "insert into landaccesslist (LandUUID, " +
582 "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " +
583 "?Flags)";
584
585 foreach (ParcelManager.ParcelAccessEntry entry in
586 parcel.landData.ParcelAccessList)
587 {
588 FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
589 ExecuteNonQuery(cmd);
590 cmd.Parameters.Clear();
591 }
592 cmd.Dispose();
593 } 552 }
553 cmd.Dispose();
554 c.Close();
594 } 555 }
595 556
596 public RegionSettings LoadRegionSettings(UUID regionUUID) 557 public RegionSettings LoadRegionSettings(UUID regionUUID)
597 { 558 {
598 RegionSettings rs = null; 559 RegionSettings rs = null;
599 560
600 lock (m_Connection) 561 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
601 { 562 c.Open();
602 MySqlCommand cmd = m_Connection.CreateCommand();
603 563
604 cmd.CommandText = "select * from regionsettings where " + 564 MySqlCommand cmd = c.CreateCommand();
605 "regionUUID = ?RegionUUID";
606 cmd.Parameters.AddWithValue("regionUUID", regionUUID);
607 565
608 IDataReader reader = ExecuteReader(cmd); 566 cmd.CommandText = "select * from regionsettings where " +
567 "regionUUID = ?RegionUUID";
568 cmd.Parameters.AddWithValue("regionUUID", regionUUID);
609 569
610 try 570 IDataReader reader = cmd.ExecuteReader();
611 {
612 if (reader.Read())
613 {
614 rs = BuildRegionSettings(reader);
615 rs.OnSave += StoreRegionSettings;
616 }
617 else
618 {
619 rs = new RegionSettings();
620 rs.RegionUUID = regionUUID;
621 rs.OnSave += StoreRegionSettings;
622 571
623 StoreRegionSettings(rs); 572 try
624 } 573 {
574 if (reader.Read())
575 {
576 rs = BuildRegionSettings(reader);
577 rs.OnSave += StoreRegionSettings;
625 } 578 }
626 finally 579 else
627 { 580 {
628 reader.Close(); 581 rs = new RegionSettings();
582 rs.RegionUUID = regionUUID;
583 rs.OnSave += StoreRegionSettings;
584
585 StoreRegionSettings(rs);
629 } 586 }
630 cmd.Dispose();
631 } 587 }
588 finally
589 {
590 reader.Close();
591 }
592 cmd.Dispose();
593 c.Close();
632 594
633 return rs; 595 return rs;
634 } 596 }
635 597
636 public void StoreRegionSettings(RegionSettings rs) 598 public void StoreRegionSettings(RegionSettings rs)
637 { 599 {
638 lock (m_Connection) 600 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
639 { 601 c.Open();
640 MySqlCommand cmd = m_Connection.CreateCommand(); 602
641 603 MySqlCommand cmd = c.CreateCommand();
642 cmd.CommandText = "replace into regionsettings (regionUUID, " + 604
643 "block_terraform, block_fly, allow_damage, " + 605 cmd.CommandText = "replace into regionsettings (regionUUID, " +
644 "restrict_pushing, allow_land_resell, " + 606 "block_terraform, block_fly, allow_damage, " +
645 "allow_land_join_divide, block_show_in_search, " + 607 "restrict_pushing, allow_land_resell, " +
646 "agent_limit, object_bonus, maturity, " + 608 "allow_land_join_divide, block_show_in_search, " +
647 "disable_scripts, disable_collisions, " + 609 "agent_limit, object_bonus, maturity, " +
648 "disable_physics, terrain_texture_1, " + 610 "disable_scripts, disable_collisions, " +
649 "terrain_texture_2, terrain_texture_3, " + 611 "disable_physics, terrain_texture_1, " +
650 "terrain_texture_4, elevation_1_nw, " + 612 "terrain_texture_2, terrain_texture_3, " +
651 "elevation_2_nw, elevation_1_ne, " + 613 "terrain_texture_4, elevation_1_nw, " +
652 "elevation_2_ne, elevation_1_se, "+ 614 "elevation_2_nw, elevation_1_ne, " +
653 "elevation_2_se, elevation_1_sw, "+ 615 "elevation_2_ne, elevation_1_se, "+
654 "elevation_2_sw, water_height, " + 616 "elevation_2_se, elevation_1_sw, "+
655 "terrain_raise_limit, terrain_lower_limit, " + 617 "elevation_2_sw, water_height, " +
656 "use_estate_sun, fixed_sun, sun_position, " + 618 "terrain_raise_limit, terrain_lower_limit, " +
657 "covenant, Sandbox, sunvectorx, sunvectory, " + 619 "use_estate_sun, fixed_sun, sun_position, " +
658 "sunvectorz) values ( ?RegionUUID, ?BlockTerraform, " + 620 "covenant, Sandbox, sunvectorx, sunvectory, " +
659 "?BlockFly, ?AllowDamage, ?RestrictPushing, " + 621 "sunvectorz) values ( ?RegionUUID, ?BlockTerraform, " +
660 "?AllowLandResell, ?AllowLandJoinDivide, " + 622 "?BlockFly, ?AllowDamage, ?RestrictPushing, " +
661 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + 623 "?AllowLandResell, ?AllowLandJoinDivide, " +
662 "?Maturity, ?DisableScripts, ?DisableCollisions, " + 624 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " +
663 "?DisablePhysics, ?TerrainTexture1, " + 625 "?Maturity, ?DisableScripts, ?DisableCollisions, " +
664 "?TerrainTexture2, ?TerrainTexture3, " + 626 "?DisablePhysics, ?TerrainTexture1, " +
665 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " + 627 "?TerrainTexture2, ?TerrainTexture3, " +
666 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " + 628 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " +
667 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " + 629 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " +
668 "?WaterHeight, ?TerrainRaiseLimit, " + 630 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " +
669 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " + 631 "?WaterHeight, ?TerrainRaiseLimit, " +
670 "?SunPosition, ?Covenant, ?Sandbox, " + 632 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " +
671 "?SunVectorX, ?SunVectorY, ?SunVectorZ)"; 633 "?SunPosition, ?Covenant, ?Sandbox, " +
672 634 "?SunVectorX, ?SunVectorY, ?SunVectorZ)";
673 FillRegionSettingsCommand(cmd, rs); 635
674 636 FillRegionSettingsCommand(cmd, rs);
675 ExecuteNonQuery(cmd); 637
676 cmd.Dispose(); 638 cmd.ExecuteNonQuery();
677 } 639 cmd.Dispose();
640 c.Close();
678 } 641 }
679 642
680 public List<LandData> LoadLandObjects(UUID regionUUID) 643 public List<LandData> LoadLandObjects(UUID regionUUID)
681 { 644 {
682 List<LandData> landData = new List<LandData>(); 645 List<LandData> landData = new List<LandData>();
683 646
684 lock (m_Connection) 647 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
648 c.Open();
649
650 MySqlCommand cmd = c.CreateCommand();
651
652 cmd.CommandText = "select * from land where " +
653 "RegionUUID = ?RegionUUID";
654
655 cmd.Parameters.AddWithValue("RegionUUID",
656 Util.ToRawUuidString(regionUUID));
657
658 IDataReader reader = cmd.ExecuteReader();
659
660 try
661 {
662 while (reader.Read())
663 {
664 LandData newLand = BuildLandData(reader);
665 landData.Add(newLand);
666 }
667 }
668 finally
685 { 669 {
686 MySqlCommand cmd = m_Connection.CreateCommand(); 670 reader.Close();
671 }
687 672
688 cmd.CommandText = "select * from land where " + 673 foreach (LandData land in landData)
689 "RegionUUID = ?RegionUUID"; 674 {
675 cmd.Parameters.Clear();
690 676
691 cmd.Parameters.AddWithValue("RegionUUID", 677 cmd.CommandText = "select * from landaccesslist " +
692 Util.ToRawUuidString(regionUUID)); 678 "where LandUUID = ?LandUUID";
693 679
694 IDataReader reader = ExecuteReader(cmd); 680 cmd.Parameters.AddWithValue("LandUUID",
681 Util.ToRawUuidString(land.GlobalID));
682
683 reader = cmd.ExecuteReader();
695 684
696 try 685 try
697 { 686 {
698 while (reader.Read()) 687 while (reader.Read())
699 { 688 {
700 LandData newLand = BuildLandData(reader); 689 land.ParcelAccessList.Add(BuildLandAccessData(reader));
701 landData.Add(newLand);
702 } 690 }
703 } 691 }
704 finally 692 finally
705 { 693 {
706 reader.Close(); 694 reader.Close();
707 } 695 }
708
709 foreach (LandData land in landData)
710 {
711 cmd.Parameters.Clear();
712
713 cmd.CommandText = "select * from landaccesslist " +
714 "where LandUUID = ?LandUUID";
715
716 cmd.Parameters.AddWithValue("LandUUID",
717 Util.ToRawUuidString(land.GlobalID));
718
719 reader = ExecuteReader(cmd);
720
721 try
722 {
723 while (reader.Read())
724 {
725 land.ParcelAccessList.Add(BuildLandAccessData(reader));
726 }
727 }
728 finally
729 {
730 reader.Close();
731 }
732 }
733 cmd.Dispose();
734 } 696 }
697 cmd.Dispose();
698 c.Close();
735 699
736 return landData; 700 return landData;
737 } 701 }
@@ -1415,41 +1379,42 @@ byte[] textureEntry = (byte[]) row["Texture"];
1415 1379
1416 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1380 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1417 { 1381 {
1418 lock (m_Connection) 1382 RemoveItems(primID);
1383
1384 MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
1385 c.Open();
1386
1387 MySqlCommand cmd = c.CreateCommand();
1388
1389 if (items.Count == 0)
1390 return;
1391
1392 cmd.CommandText = "insert into primitems ("+
1393 "invType, assetType, name, "+
1394 "description, creationDate, nextPermissions, "+
1395 "currentPermissions, basePermissions, "+
1396 "everyonePermissions, groupPermissions, "+
1397 "flags, itemID, primID, assetID, "+
1398 "parentFolderID, creatorID, ownerID, "+
1399 "groupID, lastOwnerID) values (?invType, "+
1400 "?assetType, ?name, ?description, "+
1401 "?creationDate, ?nextPermissions, "+
1402 "?currentPermissions, ?basePermissions, "+
1403 "?everyonePermissions, ?groupPermissions, "+
1404 "?flags, ?itemID, ?primID, ?assetID, "+
1405 "?parentFolderID, ?creatorID, ?ownerID, "+
1406 "?groupID, ?lastOwnerID)";
1407
1408 foreach (TaskInventoryItem item in items)
1419 { 1409 {
1420 RemoveItems(primID); 1410 cmd.Parameters.Clear();
1421
1422 MySqlCommand cmd = m_Connection.CreateCommand();
1423
1424 if (items.Count == 0)
1425 return;
1426
1427 cmd.CommandText = "insert into primitems ("+
1428 "invType, assetType, name, "+
1429 "description, creationDate, nextPermissions, "+
1430 "currentPermissions, basePermissions, "+
1431 "everyonePermissions, groupPermissions, "+
1432 "flags, itemID, primID, assetID, "+
1433 "parentFolderID, creatorID, ownerID, "+
1434 "groupID, lastOwnerID) values (?invType, "+
1435 "?assetType, ?name, ?description, "+
1436 "?creationDate, ?nextPermissions, "+
1437 "?currentPermissions, ?basePermissions, "+
1438 "?everyonePermissions, ?groupPermissions, "+
1439 "?flags, ?itemID, ?primID, ?assetID, "+
1440 "?parentFolderID, ?creatorID, ?ownerID, "+
1441 "?groupID, ?lastOwnerID)";
1442
1443 foreach (TaskInventoryItem item in items)
1444 {
1445 cmd.Parameters.Clear();
1446 1411
1447 FillItemCommand(cmd, item); 1412 FillItemCommand(cmd, item);
1448 1413
1449 ExecuteNonQuery(cmd); 1414 cmd.ExecuteNonQuery();
1450 }
1451 cmd.Dispose();
1452 } 1415 }
1416 cmd.Dispose();
1417 c.Close();
1453 } 1418 }
1454 } 1419 }
1455} 1420}