/*
* Namespace Summary
* Copyright (C) 2005+ Bogdan Damian Constantin
* E-Mail: damianbcpetro@gmail.com
* WEB: http://www.sourceforge.net/projects/dataholder
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License 2.1 or later, as
* published by the Free Software Foundation. See the included License.txt
* or http://www.gnu.org/copyleft/lesser.html for details.
*
*/
using System;
using System.Data;
using DataHolder.Containers;
using System.Collections;
namespace DataHolder.DataPersistence.DBAProvider{
/// <summary>
/// Provides Load and save beaviour from Generic Data
/// </summary>
public class DatabasePersistor
{
#region CommandsKeeper
private class CommandsKeeper: IDisposable
{
public IDbCommand InsertCmd = null, UpdateCmd = null, DeleteCmd = null;
public int [] InsertCacheColumnIndex = null, UpdateCacheColumnIndex = null, DeleteCacheColumnIndex = null, SelectCacheColumnIndex = null;
public void Dispose()
{
if(InsertCmd != null)
InsertCmd.Dispose();
InsertCmd = null;
if(UpdateCmd != null)
UpdateCmd.Dispose();
UpdateCmd = null;
if(DeleteCmd != null)
DeleteCmd.Dispose();
DeleteCmd = null;
InsertCacheColumnIndex = null;
UpdateCacheColumnIndex = null;
DeleteCacheColumnIndex = null;
SelectCacheColumnIndex = null;
}
}
#endregion
#region LoadData
#region FromDataReader
private static void LoadDataFromDataReaderInternall(IDataReader dr, GenericDataPropertiesHolder gdph, ref GenericData ge,
ref int [] CacheColumnIndex)
{
if(CacheColumnIndex == null)
CacheColumnIndex = gdph.SelectProperty.GetSelectColumnMapping(ge, dr);
ge.SuppressEvents = true;
for(int i = 0; i < CacheColumnIndex.Length; i++)
if(CacheColumnIndex[i] >= 0)
ge[i] = dr.GetValue(CacheColumnIndex[i]);
ge.SuppressEvents = false;
}
/// <summary>
/// Loads the data from Reader. This function will not call OnAfterLoad because the connection is busy fetching data
/// </summary>
/// <param name="dr"></param>
/// <param name="gdph"></param>
/// <param name="geColl"></param>
public void LoadDatesFromDataReader(IDataReader dr, GenericDataPropertiesHolder gdph, ref GenericDataCollection geColl)
{
GenericData ge;
int [] CacheColumnIndex = null;
while(dr.Read())
{
ge = (GenericData)Activator.CreateInstance(geColl.GenericDataType);
LoadDataFromDataReaderInternall(dr, gdph, ref ge, ref CacheColumnIndex);
geColl.Add(ge);
ge.AcceptChanges();
}
}
#endregion
public void LoadDates(IDbCommand cmd, CommandProvider cmdProvider, GenericDataPropertiesHolder gdph, GenericDataCollection geColl, object PersistenceInfo)
{
using(IDataReader dr = cmd.ExecuteReader())
{
LoadDatesFromDataReader(dr, gdph, ref geColl);
dr.Close();
BaseOnPersistAction action = this.GetPersistorAction(geColl.GenericDataType);
if(action != null)
foreach(GenericData ge in geColl)
action.OnAfterLoad(cmd.Connection, cmd.Transaction, this, cmdProvider, ge, gdph, PersistenceInfo);
}
}
public void LoadDates(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, GenericDataPropertiesHolder [] gdphs,
GenericDataCollection geColl, SelectCommandOption selcmdOption, object PersistenceInfo)
{
GenericDataPropertiesHolder gdph = gdphs[GetGDPHIndex(geColl.GenericDataType, gdphs)];
if(gdph == null)
throw new Exception("No GenericDataPropertiesHolder found for type: " + geColl.GenericDataType.FullName);
IDbCommand cmd = cmdProvider.GetSelectCommand(gdph, selcmdOption.Sentence, selcmdOption.OrderByInfo, selcmdOption.LockType, selcmdOption.SelectOptions);
cmd.Connection = connection;
cmd.Transaction = tran;
LoadDates(cmd, cmdProvider, gdph,geColl, PersistenceInfo);
if(selcmdOption.LoadTypedProperties)
LoadTypedPropertiesData(connection, tran, cmdProvider, gdphs, geColl, selcmdOption.DetailsLockType, PersistenceInfo);
}
public GenericDataCollection LoadDates(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, Type CollectionType,
SelectCommandOption selcmdOption, string PropertiesIdentifier, object PersistenceInfo)
{
GenericDataCollection gecoll = (GenericDataCollection)Activator.CreateInstance(CollectionType);
GenericDataPropertiesHolder [] gdphs = PersistenceManager.GetAllProperties(gecoll.GenericDataType, PropertiesIdentifier);
LoadDates(connection, tran, cmdProvider, gdphs, gecoll, selcmdOption, PersistenceInfo);
return gecoll;
}
/// <summary>
/// Loads the data from Command. This function will not call OnAfterLoad because the connection is busy fetching data
/// </summary>
/// <param name="cmd"></param>
/// <param name="gdph"></param>
/// <param name="geData"></param>
/// <returns></returns>
public bool LoadData(IDbCommand cmd, GenericDataPropertiesHolder gdph, ref GenericData geData)
{
int [] CacheColumnIndex = null;
bool ret = false;
using(IDataReader dr = cmd.ExecuteReader())
{
if(dr.Read())
{
ret = true;
LoadDataFromDataReaderInternall(dr, gdph,ref geData, ref CacheColumnIndex);
}
dr.Close();
}
return ret;
}
private static int GetGDPHIndex(Type gdtype, GenericDataPropertiesHolder [] gdphs)
{
for(int i = 0; i < gdphs.Length; i++)
if(gdphs[i].DataType == gdtype)
return i;
throw new Exception("There is no GenericDataPropertiesHolder for type: " + gdtype.FullName);
}
#region TypedPropertiesLoading
private void internallTypedDataLoading(IDbConnection connection, IDbTransaction tran, CommandProvider p_CommandProvider,
int gdphindex, GenericDataPropertiesHolder [] gdphs, FilterSentence cfi , int [] ParentPropValueIndex,
int MasterPropIndex, Containers.Property.TypedProperty tp, ref GenericData geMain, CommandLockType DetailsLockType, object PersistenceInfo)
{
bool MasterIsOK = true;
for(int i = 0; i < ParentPropValueIndex.Length; i++)
if(geMain[ParentPropValueIndex[i]] == DBNull.Value)
{
MasterIsOK = false;
break;
}
if(MasterIsOK)
{
for(int i = 0; i < ParentPropValueIndex.Length; i++)
cfi.Filters[0].ColumnValue = geMain[ParentPropValueIndex[i]];
IDbCommand SelectCommand = p_CommandProvider.GetSelectCommand(gdphs[gdphindex], cfi, null, DetailsLockType, new SelectPhraseOptions());
SelectCommand.Connection = connection;
SelectCommand.Transaction = tran;
if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericData)))
{
GenericData geToLoad = (GenericData)geMain[MasterPropIndex];
if(geToLoad == null)
geToLoad = (GenericData)Activator.CreateInstance(tp.PropertyType);
if(LoadData(SelectCommand, gdphs[gdphindex], ref geToLoad)
&& geMain[MasterPropIndex] == null)
{
geMain[MasterPropIndex] = geToLoad;
geToLoad.Parent = geMain;
}
LoadTypedPropertiesData(connection, tran, p_CommandProvider, gdphs, geToLoad, DetailsLockType, PersistenceInfo);
}
else if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericDataCollection)))
{
GenericDataCollection collToLoad = (GenericDataCollection)geMain[MasterPropIndex];
if(collToLoad == null)
collToLoad = (GenericDataCollection)Activator.CreateInstance(tp.PropertyType);
LoadDates(SelectCommand, p_CommandProvider, gdphs[gdphindex], collToLoad, PersistenceInfo);
if(collToLoad.Count > 0 && geMain[MasterPropIndex] == null)
{
geMain[MasterPropIndex] = collToLoad;
collToLoad.Parent = geMain;
}
LoadTypedPropertiesData(connection, tran, p_CommandProvider, gdphs, collToLoad, DetailsLockType, PersistenceInfo);
}
}
}
public void LoadTypedPropertiesData(IDbConnection connection, IDbTransaction tran, CommandProvider p_CommandProvider,GenericDataPropertiesHolder [] gdphs,
GenericData geMain, CommandLockType DetailsLockType, object PersistenceInfo)
{
int currentgdph = GetGDPHIndex(geMain.GetType(), gdphs);
if(gdphs[currentgdph].TypeDataRelations == null)
return;
foreach(DBAProvider.DataRelation dr in gdphs[currentgdph].TypeDataRelations)
{
if(!dr.LoadWithMaster)
continue;
FilterSentence sentence = new FilterSentence();
int [] ParentPropValueIndex = new int[dr.RelationPropertyMapping.Length];
for(int i=0; i < ParentPropValueIndex.Length; i++)
{
ParentPropValueIndex[i] = geMain.Properties.IndexOf(dr.RelationPropertyMapping[i].MasterProperty);
sentence.Filters.Add(new ColumnFilterInfo(dr.RelationPropertyMapping[i].DetailProperty, FilterOperator.Equal , null));
}
int MasterPropIndex = geMain.Properties.IndexOf(dr.PropertyName);
Containers.Property.TypedProperty tp = (Containers.Property.TypedProperty)geMain.Properties[MasterPropIndex];
int gdphindex = -1;
if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericData)))
gdphindex = GetGDPHIndex(tp.PropertyType, gdphs);
else if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericDataCollection)))
{
Containers.GenericDataCollection tmpcoll = (Containers.GenericDataCollection)Activator.CreateInstance(tp.PropertyType);
gdphindex = GetGDPHIndex(tmpcoll.GenericDataType, gdphs);
}
internallTypedDataLoading(connection, tran, p_CommandProvider, gdphindex, gdphs, sentence, ParentPropValueIndex, MasterPropIndex, tp, ref geMain, DetailsLockType, PersistenceInfo);
}
}
private void LoadTypedPropertiesData(IDbConnection connection, IDbTransaction tran, CommandProvider p_CommandProvider,GenericDataPropertiesHolder [] gdphs,
GenericDataCollection gecoll, CommandLockType DetailsLockType, object PersistenceInfo)
{
int currentgdph = GetGDPHIndex(gecoll.GenericDataType, gdphs);
if(gecoll.Count == 0 || gdphs[currentgdph].TypeDataRelations == null)
return;
Containers.Property.PropertyCollection pc = ((GenericData)gecoll.GetObjectAt(0)).Properties;
foreach(DBAProvider.DataRelation dr in gdphs[currentgdph].TypeDataRelations)
{
if(!dr.LoadWithMaster)
continue;
FilterSentence sentence = new FilterSentence(dr.RelationPropertyMapping.Length,0);
int [] ParentPropValueIndex = new int[dr.RelationPropertyMapping.Length];
for(int i=0; i < ParentPropValueIndex.Length; i++)
{
ParentPropValueIndex[i] = pc.IndexOf(dr.RelationPropertyMapping[i].MasterProperty);
sentence.Filters.Add(new ColumnFilterInfo(dr.RelationPropertyMapping[i].DetailProperty, FilterOperator.Equal , null));
}
int MasterPropIndex = pc.IndexOf(dr.PropertyName);
Containers.Property.TypedProperty tp = (Containers.Property.TypedProperty)pc[MasterPropIndex];
int gdphindex = -1;
if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericData)))
gdphindex = GetGDPHIndex(tp.PropertyType, gdphs);
else if(tp.PropertyType.IsSubclassOf(typeof(Containers.GenericDataCollection)))
{
Containers.GenericDataCollection tmpcoll = (Containers.GenericDataCollection)Activator.CreateInstance(tp.PropertyType);
gdphindex = GetGDPHIndex(tmpcoll.GenericDataType, gdphs);
}
for(int i = 0; i < gecoll.Count; i++)
{
GenericData ge = (GenericData)gecoll.GetObjectAt(i);
internallTypedDataLoading(connection, tran, p_CommandProvider, gdphindex, gdphs, sentence, ParentPropValueIndex, MasterPropIndex, tp, ref ge, DetailsLockType, PersistenceInfo);
}
}
}
#endregion
#region LoadPagedDates
public int LoadPagedDates(IDataReader dr, ref GenericDataPropertiesHolder gdph, ref GenericDataCollection geColl, int PageSize,
int CurrentPageIndex, int EmptySpacesInPage)
{
GenericData ge;
int [] CacheColumnIndex = null;
int FirstRecordIndex = CurrentPageIndex * PageSize;
int RowsCount = 0;
while(dr.Read())
{
RowsCount ++;
if(RowsCount > FirstRecordIndex && RowsCount <= FirstRecordIndex + PageSize - EmptySpacesInPage)
{
ge = (GenericData)Activator.CreateInstance(geColl.GenericDataType);
LoadDataFromDataReaderInternall(dr, gdph, ref ge, ref CacheColumnIndex);
geColl.Add(ge);
}
}
geColl.AcceptChanges();
return RowsCount;
}
public int LoadPagedDates(IDbCommand cmd, ref GenericDataPropertiesHolder gdph, ref GenericDataCollection geColl, int PageSize, int CurrentPageIndex, int EmptySpacesInPage)
{
using(IDataReader dr = cmd.ExecuteReader())
{
int RowsCount = LoadPagedDates(dr, ref gdph, ref geColl, PageSize, CurrentPageIndex, EmptySpacesInPage);
dr.Close();
return RowsCount;
}
}
#endregion
#endregion
#region Save
private void SaveData(CommandProvider cmdProvider, IDbCommand cmd, int [] CacheColumnIndex, int [] SelectCacheColumnIndex,
GenericData ge, GenericDataPropertiesHolder gdph, object PersistenceInfo)
{
cmdProvider.BeforeSaveEntity(cmd.Connection, cmd.Transaction, ge, gdph, PersistenceInfo);
for(int i = 0; i < CacheColumnIndex.Length; i++)
{
IDataParameter param = (IDataParameter)cmd.Parameters[i];
param.Value = ge[CacheColumnIndex[i], UtilVersion.GetGenericDataVersion(param.SourceVersion)];
}
IDataReader dr = cmd.ExecuteReader();
if(dr.RecordsAffected <= 0)
throw new Exception("No Records Affected by command");
if((cmd.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord
|| cmd.UpdatedRowSource == UpdateRowSource.Both)
&& dr.Read())
LoadDataFromDataReaderInternall(dr, gdph, ref ge, ref SelectCacheColumnIndex);
dr.Close();
dr.Dispose();
// TO BE developed
// foreach(IDataParameter param in cmd.Parameters)
// if(param.Direction == ParameterDirection.InputOutput
// || param.Direction == ParameterDirection.Output)
// ge[param.SourceColumn] = param.Value;
cmdProvider.AfterSaveEntity(cmd.Connection, cmd.Transaction, ge, gdph, PersistenceInfo);
}
private void SaveDataInternall(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, GenericDataPropertiesHolder [] gdphs,
bool SaveTypedProperties, GenericData ge, ref CommandsKeeper cmds, int currentgdph, object PersistenceInfo)
{
BaseOnPersistAction action = this.GetPersistorAction(ge.GetType());
if(action != null)
action.OnBeforeSaveEntity(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
if(ge.State == GenericDataState.Added)
{
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesBeforeMaster(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
if(cmds.InsertCmd == null)
{
cmds.InsertCmd = cmdProvider.GetInsertCommand(ge, gdphs[currentgdph]);
cmds.InsertCmd.Connection = connection;
cmds.InsertCmd.Transaction = tran;
cmds.InsertCacheColumnIndex = gdphs[currentgdph].InsertProperty.GetSaveColumnMapping(ge, cmds.InsertCmd.Parameters);
}
if(action != null)
action.OnBeforeInsert(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
SaveData(cmdProvider, cmds.InsertCmd, cmds.InsertCacheColumnIndex, cmds.SelectCacheColumnIndex, ge, gdphs[currentgdph], PersistenceInfo);
if(action != null)
action.OnAfterInsert(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesAfterMasterSave(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
}
else if(ge.State == GenericDataState.Modified)
{
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesBeforeMaster(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
if(cmds.UpdateCmd == null)
{
cmds.UpdateCmd = cmdProvider.GetUpdateCommand(ge, gdphs[currentgdph]);
cmds.UpdateCmd.Connection = connection;
cmds.UpdateCmd.Transaction = tran;
cmds.UpdateCacheColumnIndex = gdphs[currentgdph].UpdateProperty.GetSaveColumnMapping(ge, cmds.UpdateCmd.Parameters);
}
if(action != null)
action.OnBeforeUpdate(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
SaveData(cmdProvider, cmds.UpdateCmd, cmds.UpdateCacheColumnIndex, cmds.SelectCacheColumnIndex, ge, gdphs[currentgdph], PersistenceInfo);
if(action != null)
action.OnAfterUpdate(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesAfterMasterSave(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
}
else if(ge.State == GenericDataState.Deleted)
{
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesBeforeMaster(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
if(cmds.DeleteCmd == null)
{
cmds.DeleteCmd = cmdProvider.GetDeleteCommand(ge, gdphs[currentgdph]);
cmds.DeleteCmd.Connection = connection;
cmds.DeleteCmd.Transaction = tran;
cmds.DeleteCacheColumnIndex = gdphs[currentgdph].DeleteProperty.GetSaveColumnMapping(ge, cmds.DeleteCmd.Parameters);
}
if(action != null)
action.OnBeforeDelete(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
SaveData(cmdProvider, cmds.DeleteCmd, cmds.DeleteCacheColumnIndex, cmds.SelectCacheColumnIndex, ge, gdphs[currentgdph], PersistenceInfo);
if(action != null)
action.OnAfterDelete(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesAfterMasterSave(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
}
else
{
//when master is unchanged save the typed dates
if(SaveTypedProperties && gdphs[currentgdph].TypeDataRelations != null)
{
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesBeforeMaster(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
//it might happen that the master is modified by the subentities
if(ge.State == GenericDataState.Modified)
{
if(cmds.UpdateCmd == null)
{
cmds.UpdateCmd = cmdProvider.GetUpdateCommand(ge, gdphs[currentgdph]);
cmds.UpdateCmd.Connection = connection;
cmds.UpdateCmd.Transaction = tran;
cmds.UpdateCacheColumnIndex = gdphs[currentgdph].UpdateProperty.GetSaveColumnMapping(ge, cmds.UpdateCmd.Parameters);
}
if(action != null)
action.OnBeforeUpdate(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
SaveData(cmdProvider, cmds.UpdateCmd, cmds.UpdateCacheColumnIndex, cmds.SelectCacheColumnIndex, ge, gdphs[currentgdph], PersistenceInfo);
if(action != null)
action.OnAfterUpdate(connection, tran, this, cmdProvider, ge, gdphs[currentgdph], PersistenceInfo);
}
foreach(DataRelation dr in gdphs[currentgdph].TypeDataRelations)
SaveTypedDatesAfterMasterSave(connection, tran, cmdProvider, gdphs, ge, dr, PersistenceInfo);
}
}
}
public void SaveData(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider,
GenericDataPropertiesHolder [] gdphs, bool SaveTypedProperties, GenericData ge, object PersistenceInfo)
{
CommandsKeeper cmds = new CommandsKeeper();
int currentgdph = GetGDPHIndex(ge.GetType(), gdphs);
SaveDataInternall(connection, tran, cmdProvider, gdphs, SaveTypedProperties, ge, ref cmds, currentgdph, PersistenceInfo);
cmds.Dispose();
}
public void SaveDates(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, GenericDataPropertiesHolder [] gdphs,
bool SaveTypedProperties, GenericDataCollection geColl, object PersistenceInfo)
{
CommandsKeeper cmds = new CommandsKeeper();
int currentgdph = GetGDPHIndex(geColl.GenericDataType, gdphs);
for(int geindex = 0; geindex < geColl.Count; geindex ++)
{
GenericData ge = (GenericData)geColl.GetObjectAt(geindex);
SaveDataInternall(connection, tran, cmdProvider, gdphs, SaveTypedProperties, ge, ref cmds, currentgdph, PersistenceInfo);
}
}
private void SaveTypedDatesBeforeMaster(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, GenericDataPropertiesHolder [] gdphs,
GenericData ge, DataRelation dr, object PersistenceInfo)
{
if(!dr.SaveWithMaster)
return;
int MasterPropIndex = ge.Properties.IndexOf(dr.PropertyName);
if( ge[MasterPropIndex] == null)
return;
CommandsKeeper cmds = new CommandsKeeper();
if(ge.Properties[MasterPropIndex].PropertyType.IsSubclassOf(typeof(GenericData)))
{
GenericData gedet = (GenericData)ge[MasterPropIndex];
int currentgdph = GetGDPHIndex(ge.Properties[MasterPropIndex].PropertyType, gdphs);
if((gedet.State == GenericDataState.Added && dr.InsertOrder == RelationDirection.DetailMaster)
|| (gedet.State == GenericDataState.Modified && dr.UpdateOrder == RelationDirection.DetailMaster))
{
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
if (ge.State != GenericDataState.Deleted)//don't modify the parent if the parent status is deleted
foreach (RelationPropertyMapping rpm in dr.RelationPropertyMapping)
ge[rpm.MasterProperty] = gedet[rpm.DetailProperty];
}
//in case the detail is a entity it myghtbe that the master entity is referencing the detail entity
else if (gedet.State == GenericDataState.Deleted && dr.DeleteOrder == RelationDirection.MasterDetail
&& ge.State != GenericDataState.Deleted)
{
foreach(RelationPropertyMapping rpm in dr.RelationPropertyMapping)
ge[rpm.MasterProperty] = DBNull.Value;
}
}
else if(ge.Properties[MasterPropIndex].PropertyType.IsSubclassOf(typeof(GenericDataCollection)))
{
GenericDataCollection gedets = (GenericDataCollection)ge[MasterPropIndex];
int [] masterprops = new int[dr.RelationPropertyMapping.Length];
int [] detprops = new int[dr.RelationPropertyMapping.Length];
Containers.Property.PropertyCollection pc = GenericData.TCollection.GetProperties(gedets.GenericDataType);
for(int i = 0; i < dr.RelationPropertyMapping.Length; i++)
{
masterprops[i] = ge.Properties.IndexOf(dr.RelationPropertyMapping[i].MasterProperty);
detprops[i] = pc.IndexOf(dr.RelationPropertyMapping[i].DetailProperty);
}
int currentgdph = GetGDPHIndex(gedets.GenericDataType, gdphs);
for(int detindex = 0; detindex < gedets.Count; detindex++)
{
GenericData gedet = (GenericData)gedets.GetObjectAt(detindex);
if((gedet.State == GenericDataState.Added && dr.InsertOrder == RelationDirection.DetailMaster)
|| (gedet.State == GenericDataState.Modified && dr.UpdateOrder == RelationDirection.DetailMaster))
{
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
}
}
}
cmds.Dispose();
}
private void SaveTypedDatesAfterMasterSave(IDbConnection connection, IDbTransaction tran, CommandProvider cmdProvider, GenericDataPropertiesHolder [] gdphs,
GenericData ge, DataRelation dr, object PersistenceInfo)
{
if(!dr.SaveWithMaster)
return;
int MasterPropIndex = ge.Properties.IndexOf(dr.PropertyName);
if( ge[MasterPropIndex] == null)
return;
CommandsKeeper cmds = new CommandsKeeper();
if(ge.Properties[MasterPropIndex].PropertyType.IsSubclassOf(typeof(GenericData)))
{
GenericData gedet = (GenericData)ge[MasterPropIndex];
int currentgdph = GetGDPHIndex(ge.Properties[MasterPropIndex].PropertyType, gdphs);
if((gedet.State == GenericDataState.Added && dr.InsertOrder == RelationDirection.MasterDetail)
|| (gedet.State == GenericDataState.Modified && dr.UpdateOrder == RelationDirection.MasterDetail))
{
foreach(RelationPropertyMapping rpm in dr.RelationPropertyMapping)
gedet[rpm.DetailProperty] = ge[rpm.MasterProperty];
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
}
else if(gedet.State == GenericDataState.Deleted || gedet.State == GenericDataState.Unchanged)
{
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
}
}
else if(ge.Properties[MasterPropIndex].PropertyType.IsSubclassOf(typeof(GenericDataCollection)))
{
GenericDataCollection gedets = (GenericDataCollection)ge[MasterPropIndex];
int [] masterprops = new int[dr.RelationPropertyMapping.Length];
int [] detprops = new int[dr.RelationPropertyMapping.Length];
Containers.Property.PropertyCollection pc = GenericData.TCollection.GetProperties(gedets.GenericDataType);
//because the props seting is done for multiple objects in the collection a properti matching index is done
for(int i = 0; i < dr.RelationPropertyMapping.Length; i++)
{
masterprops[i] = ge.Properties.IndexOf(dr.RelationPropertyMapping[i].MasterProperty);
detprops[i] = pc.IndexOf(dr.RelationPropertyMapping[i].DetailProperty);
}
int currentgdph = GetGDPHIndex(gedets.GenericDataType, gdphs);
for(int detindex = 0; detindex < gedets.Count; detindex++)
{
GenericData gedet = (GenericData)gedets.GetObjectAt(detindex);
if((gedet.State == GenericDataState.Added && dr.InsertOrder == RelationDirection.MasterDetail)
|| (gedet.State == GenericDataState.Modified && dr.UpdateOrder == RelationDirection.MasterDetail))
{
for(int i = 0; i < masterprops.Length; i++)
gedet[detprops[i]] = ge[masterprops[i]];
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
}
else if(gedet.State == GenericDataState.Deleted || gedet.State == GenericDataState.Unchanged)
{
SaveDataInternall(connection, tran, cmdProvider, gdphs, true, gedet, ref cmds, currentgdph, PersistenceInfo);
}
}
}
cmds.Dispose();
}
#endregion
#region OnPersistActions
protected Hashtable PersistenceActions = new Hashtable(3);
public BaseOnPersistAction GetPersistorAction(Type type)
{
return (BaseOnPersistAction)PersistenceActions[type];
}
public void AddPersistorAction(BaseOnPersistAction action)
{
PersistenceActions[action.CoveredType] = action;
}
#endregion
}
}
|