/// <summary> /// Reads the middle table of many-to-many relationship. Bad performance currently, because it reads the /// middle file everytime a record is read. /// </summary> /// <param name="rec"></param> public void ReadMTM(BaseClass rec) { foreach (MTMRelationInfo mtmInfo in rec.MTMInfoList()) { String filepath = Path.Combine(ctx.DatabaseFolder, mtmInfo.tableName) + ".dat"; //mtm middle tablo yolu Stream mtmStream = File.OpenRead(filepath); int line = Convert.ToInt32(mtmStream.Length / (sizeof(int) * 3)); List <MTMRec> mtmRecs = new List <MTMRec>(); //middle tablo kayıtları for (int i = 0; i < line; i++) { Tuple <DKDB.BaseClass, Dictionary <PropertyInfo, int> > fillingLog; fillingLog = FileOps.ReadSingleRecord(mtmStream, i + 1, typeof(MTMRec)); mtmRecs.Add((MTMRec)fillingLog.Item1); } mtmStream.Close(); int my_id_column = WhoAmI(mtmInfo.tableName); //MTMRec içinde id1 mi benim sütunum yoksa id2 mi? ctx'teki sıraya göre kontrol edilir MTMReq mtmReq = new MTMReq(rec, mtmInfo.OwnMTMProp); foreach (MTMRec mtmRec in mtmRecs) //her bir middle tablo kaydı için: { if (my_id_column == 1 && mtmRec.id_1 == rec.id) { mtmReq.AddOppId(mtmRec.id_2);//opposite id } else if (my_id_column == 2 && mtmRec.id_2 == rec.id) { mtmReq.AddOppId(mtmRec.id_1);//opposite id } } KeyValuePair <string, Tuple <Type, Type> > kp = BaseClass.AllMTMRelations.FirstOrDefault(r => r.Key == mtmInfo.tableName); object opposite_dbset = ctx.GetDBSetByType(my_id_column == 1 ? kp.Value.Item2 : kp.Value.Item1); object[] parameters = new object[1]; parameters[0] = mtmReq; //list of ids of the records that we want to read from opposite db PropertyInfo fi = opposite_dbset.GetType().GetProperty("MTMReqList"); List <MTMReq> rtbfMTM = fi.GetValue(opposite_dbset) as List <MTMReq>; rtbfMTM.GetType().GetMethod("Add").Invoke(rtbfMTM, parameters); } }
/// <summary> /// Completes changes in the dbset chosen by the command. /// </summary> /// <param name="command">AddDirectly, AddChilds, Update, Remove</param> public bool SaveChanges(char[] com) { String command = new string(com); bool result = false; if (command == "AddOTM") { while (recordsToAddAsOTM.Count() != 0) { Tuple <object, object, PropertyInfo> rec = recordsToAddAsOTM[0]; OpenMainWrite(); rec.Item3.SetValue(rec.Item2, rec.Item1); int fk = FileOps.Add(mainFile, removedIndexes, (BaseClass)rec.Item2); rec.Item2.GetType().GetProperty(rec.Item3.Name).SetValue(rec.Item2, fk); result = true; } } else if (command == "AddDirectly") { //0. elemanlar ile işlem yapma nedeni: //Bir ekleme işlemi yapılırken, içinde çocuk nesne var ise, bir şekilde üzerinde çalışılan //listenin sonuna yeni kayıt eklenmesine neden olabilir. OpenMainWrite(); while (recordsToAddDirectly.Count() != 0) { result = true; int id = FileOps.Add(mainFile, removedIndexes, recordsToAddDirectly[0]); recordsToAddDirectly[0].id = id; allRecords.Add(recordsToAddDirectly[0]); recordsToAddDirectly.RemoveAt(0); } mainFile.Close(); } else if (command == "AddChilds") { OpenMainWrite(); while (recordsToAddAsOTO.Count() != 0) { result = true; //item1=parent, item2=child T record = (T)recordsToAddAsOTO[0].Item2; int fk = FileOps.Add(mainFile, removedIndexes, record); record.id = fk; Type ownerType = recordsToAddAsOTO[0].Item1.GetType(); Type ownerDbSetType = ctx.dbsetTypes.Where(a => a.ToString().Equals(ownerType.ToString())).ElementAt(0); object ownerDbSet = ctx.GetDBSetByType(ownerDbSetType); object[] parameters = new object[1]; parameters[0] = (BaseClass)recordsToAddAsOTO[0].Item1; //Explained under recordsToAddAsOTO declaration. ownerDbSet.GetType().GetMethod("Update").Invoke(ownerDbSet, parameters); allRecords.Add(record); recordsToAddAsOTO.RemoveAt(0); } mainFile.Close(); } else if (command == "Update") { OpenMainWrite(); while (Updates.Count() != 0) { result = true; T record = Updates[0]; FileOps.Overwrite(mainFile, record); Updates.RemoveAt(0); } mainFile.Close(); } else if (command == "Remove") { OpenMainWrite(); while (recordsToRemove.Count() != 0) { result = true; recordsToRemove[0].GetType().GetProperty("removed").SetValue(recordsToRemove[0], true); FileOps.Remove(mainFile, metaFile, recordsToRemove[0]); if (!ctx.removed.Any(kp => kp.Key == typeof(T))) { ctx.removed.Add(typeof(T), new List <int>()); } ctx.removed.FirstOrDefault(kp => kp.Key == typeof(T)).Value .Add((int)recordsToRemove[0].id); recordsToRemove.RemoveAt(0); } mainFile.Close(); } else if (command == "UpdateAfterRemoval") //silinmiş bir kayda referans olanların foreign keylerini -1 yapacak { List <PropertyInfo> toChangeColumns = new List <PropertyInfo>(); Dictionary <int, List <int> > toChange = new Dictionary <int, List <int> >(); foreach (KeyValuePair <Type, List <int> > kp in ctx.removed) { List <PropertyInfo> props = this.GetType().GetGenericArguments()[0].GetProperties().ToList(); foreach (PropertyInfo info in props) { if (!info.PropertyType.IsGenericType && info.PropertyType.Name.Equals(kp.Key.Name)) { toChangeColumns.Add(info); foreach (int id in kp.Value) //null yapılacak id { toChange.Add(id, new List <int>()); } } else if (info.PropertyType.IsGenericType && info.PropertyType.GetGenericArguments()[0].Name == kp.Key.Name) { //remove from mtm } } } foreach (T rec in allRecords) { foreach (PropertyInfo column in toChangeColumns) { foreach (KeyValuePair <int, List <int> > kp in toChange) { BaseClass child_rec = (BaseClass)rec.GetType().GetProperty(column.Name).GetValue(rec); if (child_rec.id == kp.Key) { rec.GetType().GetProperty(column.Name).SetValue(rec, null); kp.Value.Add(rec.id); } } } } foreach (PropertyInfo column in toChangeColumns) { OpenMainWrite(); FileOps.MakeReferenceNull(mainFile, column, typeof(T), toChange); mainFile.Close(); } } return(result); }