Click here to Skip to main content
15,886,038 members
Articles / Desktop Programming / Windows Forms

Three-tier .NET Application Utilizing Three ORM Technologies

Rate me:
Please Sign up or sign in to vote.
4.95/5 (118 votes)
30 Jan 2010CPOL109 min read 163.9K   4.4K   437  
LINQ to SQL, Entity Framework, and NHibernate used in a parallel fashion in a three-tier WinForms application.
#define SQLSERVER2005
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using du=DomainUtil;
using dal = DalEF;
using s = System;
using sql = ServerUtil.sql;
using ns=ServiceEF;
using si=ServiceInterface;
using u=Util;
using sm=System.ServiceModel;
using gt=GlobalType;
using su=ServerUtil;
using sch=ServerUtil.Schema;

namespace ServiceEF
{
	static class Helper
	{
		#region CodeWindow 023, CodeWindow 059
		public static s.Data.EntityKey CreateEntityKey(int iID, string strQualifiedEntitySetName)
		{
			IEnumerable<KeyValuePair<string, object>> entityKeyValues =
				new KeyValuePair<string, object>[] {
					new KeyValuePair<string, object>("ID", iID) };

			return  new s.Data.EntityKey(strQualifiedEntitySetName, entityKeyValues);
		}
		#endregion
		#region CodeWindow 060
		public static int? GetFK<T>(/*this */s.Data.Objects.DataClasses.EntityReference<T> refr) where T : class, s.Data.Objects.DataClasses.IEntityWithRelationships 
		{
			if(refr == null)
				throw new s.Exception("ServiceEF:21");
			if(refr.EntityKey == null)
			{
				if(refr.Value!=null)
					throw new s.Exception("ServiceEF:27");
				return null;
			}
		
		//	can be null if not yet loaded even if FK is not null
		//	if(refr.Value == null)
		//		throw new s.Exception("ServiceEF:31");

			if(refr.EntityKey.EntityKeyValues ==null)
				throw new s.Exception("ServiceEF:33");
			if(refr.EntityKey.EntityKeyValues.Length !=1)
				throw new s.Exception("ServiceEF:35");
			return (int)refr.EntityKey.EntityKeyValues.First().Value;
		}
		#endregion
		#region CodeWindow 061
		public static void EnsureFK<T>(/*this */s.Data.Objects.DataClasses.EntityReference<T> refr, s.Data.Objects.ObjectContext ctx, int? iID) where T: class, s.Data.Objects.DataClasses.IEntityWithRelationships
		{
			int? iCurrentID = Helper.GetFK(refr);
			if(iCurrentID == iID)
				return;
			if(iCurrentID != null)
				refr.Value = null;
			else
			{
				if(refr.Value != null)
					throw new s.Exception();
			}
			if(iID != null)
				refr.EntityKey = new System.Data.EntityKey(ctx.GetType().Name + "." + typeof(T).Name, /*typeof(T).Name +*/ "ID", iID.Value);
		}
		#endregion
		public static T TryGetByID<T>(/*this */s.Data.Objects.ObjectContext ctx, int iID) where T : class, s.Data.Objects.DataClasses.IEntityWithKey 
		{
			IEnumerable<KeyValuePair<string, object>> entityKeyValues =
				new KeyValuePair<string, object>[]
				{
					new KeyValuePair<string, object>("ID", iID) 
				};

			s.Data.EntityKey key = new s.Data.EntityKey(ctx.GetType().Name + "." + typeof(T).Name, entityKeyValues);
			object obj = null;
			if(ctx.TryGetObjectByKey(key, out obj))
				return (T)obj;
			return null;
		}
		#region CodeWindow 025, CodeWindow 062
		public static void SetAllPropsAsModified(dal.LekEntities ctx, object entity)
		{
			s.Data.Objects.ObjectStateEntry aObjectStateEntry = ctx.ObjectStateManager.GetObjectStateEntry(entity);
			s.Collections.ObjectModel.ReadOnlyCollection<s.Data.Common.FieldMetadata> collFieldMetadatas
			 = aObjectStateEntry.CurrentValues.DataRecordInfo.FieldMetadata;
			foreach(var propertyName in collFieldMetadatas.Select(o => o.FieldType.Name))
			{
				if(propertyName == "ID")
					continue;
				if(propertyName == "timestamp")
					continue;
				aObjectStateEntry.SetModifiedProperty(propertyName);
			}
		}
		#endregion
		#region CodeWindow 024, CodeWindow 066
		public static Byte[] CreateORMRowVersion(gt.RowVersion aRowVersion)
		{
			if(aRowVersion==null)
				return null;
			return aRowVersion.GetCopyOfData();
		}
		#endregion
	}

	[sm.ServiceBehavior(InstanceContextMode=sm.InstanceContextMode.Single, ConcurrencyMode=sm.ConcurrencyMode.Multiple)]
	public class Service : si.IService
	{
		class BudgetDataAccess : su.BudgetPredicateUtil.IBudgetDataAccess
		{
			dal.LekEntities _ctx;
			public s.DateTime GetDateOfTrans(int iTransactionID)
			{
				return _ctx.Transaction.Where(o=>o.ID==iTransactionID).Select(o=>o.Instant).SingleOrDefault();
			}
			public SortedList<int, su.BudgetPredicateUtil.VSPost> GetSortedListOfPostsByID()
			{
				IEnumerable<dal.Post> strm = _ctx.Post.OrderBy(o=>o.ID);
				SortedList<int, su.BudgetPredicateUtil.VSPost> lstPosts = new SortedList<int,su.BudgetPredicateUtil.VSPost>(strm.Count());
				foreach(dal.Post o in strm)
				{
					lstPosts.Add(o.ID, new su.BudgetPredicateUtil.VSPost(o.ID, o.Instant));
				}
				return lstPosts;
			}
			public BudgetDataAccess(dal.LekEntities ctx)
			{
				_ctx = ctx;
			}
		}

//		static string st_DBCONN;
//		static string st_CONN;
		string _strDBCONN;
		string _strCONN;
		static string CreateConnectionString(string strDBConn)
		{
			string st_CONNFmt = "metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=\"{0};MultipleActiveResultSets=True;\"";
			return string.Format(st_CONNFmt, strDBConn);
		}
//		static C()
//		{
//			st_DBCONN = s.Configuration.ConfigurationManager.AppSettings["DBConn"];
//			if(string.IsNullOrEmpty(st_DBCONN))
//				return;
//			st_CONN = CreateConnectionString(st_DBCONN);
//		}
		string CONN
		{
			get
			{
//				if(_strCONN !=null)
					return _strCONN;
//				return st_CONN;
			}
		}
//		string DBCONN
//		{
//			get
//			{
//				if(_strDBCONN !=null)
//					return _strDBCONN;
//				return st_DBCONN;
//			}
//		}
		public Service(){;}
		public Service(string strDBConn, string strDBInitString)
		{
//			if(strDBConn!=null)
//			{
				_strDBCONN = strDBConn;
				_strCONN = CreateConnectionString(strDBConn);
//			}
			if(strDBInitString!=null)
			{
				this.ClearDatabase();
				this.InitDatabase(strDBInitString);
			}
		}
		
	
		DTO.Participant[] CreateArrayOfSerializableParticipants(du.Participants aParticipants)
		{
			return aParticipants.GetArryOfObjects().Select(o=>new DTO.Participant(o.ID, o.Name)).ToArray();
		}
		du.Participants CreateDomainParticipants(DTO.Participant[] arr)
		{
			return new du.Participants(arr.Select(o=>(gt.IParticipant)o).ToList());
		}
	
		#region GetCounts
		public int GetDltAllocAccntCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.DltAllocAccnt.Count();
			}
		}
		public int GetNWAccntCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.NWAccnt.Count();
			}
		}
		public int GetParticipantCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.Participant.Count();
			}
		}
		public int GetOwnershipCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.Ownership.Count();
			}
		}
		public int GetPostCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.Post.Count();
			}
		}
		public int GetTransactionCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.Transaction.Count();
			}
		}
		public int GetItemCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.Item.Count();
			}
		}
		public int GetDltAllocCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.DltAlloc.Count();
			}
		}
		public int GetNWAccntDltCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.NWAccntDlt.Count();
			}
		}
		public int GetWashDltCount(int? iExpected)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return ctx.WashDlt.Count();
			}
		}
		#endregion

		void TestGetUnpostedTransactions()
		{
		//	ClearDatabase();
			DTO.TransPred aTransPred = new DTO.UnPostedTransPred();
		//	st_log.Debug("VerySimpleTest2 Starting.");
			DTO.Transaction[] arr = GetTransactions(aTransPred, 2);
		//	st_log.Debug("VerySimpleTest2 Completed: "+ arr.Length +" transactions.");
		}
		void TestGetItems()
		{
		//	ClearDatabase();
			DTO.TransPred aTransPred = new DTO.UnPostedTransPred();
			DTO.ItemEx[] arr = GetItemsInTransactions(aTransPred);
		}
		public void Test()
		{
		//	TestGetItems();
		}

		#region ClearDatabase
		void ClearDatabase(s.Data.SqlClient.SqlConnection conn)
		{
			s.Data.SqlClient.SqlCommand cmd = conn.CreateCommand();
			cmd.CommandText = "ClearData";
			cmd.CommandType = System.Data.CommandType.StoredProcedure;
			cmd.ExecuteNonQuery();
		}
		public void ClearDatabase()
		{
			using(s.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(_strDBCONN))
			{
				conn.Open();
				ClearDatabase(conn);
			}
		}
		#endregion

		#region InitDatabase
		void InitDatabase(string str, dal.LekEntities ctx)
		{
			#region string prep
			str = str.Replace("\t", ""); 
			str = str.Replace("\r", ""); 
			str = str.Replace(" ", "");
			str = str.Replace("Table:", "\a");
			#endregion

			#region locals
			string[] arrTableInitSpecs = str.Split('\a');
			string strRecordSpecs;
			string[] arrRecordSpecs;
			int iTable=1;

			#region Created Entities
			List<dal.Participant>	lstParticipants		= new List<dal.Participant	>();
			List<dal.NWAccnt>		lstNWAccnts			= new List<dal.NWAccnt		>();
			List<dal.DltAllocAccnt> lstDltAllocAccnts	= new List<dal.DltAllocAccnt>();
			List<dal.Post>			lstPosts			= new List<dal.Post			>();
			List<dal.Transaction>	lstTransactions		= new List<dal.Transaction	>();
			List<dal.Item>			lstItems			= new List<dal.Item			>();
			#endregion
			#endregion

			#region Participant
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "Participant")
				throw new Exception("Expected Participant, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
				dal.Participant o = new dal.Participant();
				o.Name = strRecordSpec;
				o.ID = i;
				ctx.AddToParticipant(o);
				lstParticipants.Add(o);
			}
			ctx.SaveChanges();
			#endregion

			#region NWAccnt
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "NWAccnt")
			    throw new Exception("Expected NWAccnt, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.NWAccnt o = new dal.NWAccnt();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
			    o.Name = arrFieldSpecs[0];
				o.Budgeted = (arrFieldSpecs[1]=="1"?true:false);
			    ctx.AddToNWAccnt(o);
				lstNWAccnts.Add(o);
				ctx.SaveChanges();//here instead of after the loop so it gets added to the database in the same order
			}
			#endregion

			#region DltAllocAccnt
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "DltAllocAccnt")
			    throw new Exception("Expected NWAccnt, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.DltAllocAccnt o = new dal.DltAllocAccnt();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
			    o.Name = arrFieldSpecs[0];
				o.Budgeted = (arrFieldSpecs[1]=="1"?true:false);
			    ctx.AddToDltAllocAccnt(o);
				lstDltAllocAccnts.Add(o);
				ctx.SaveChanges();//here instead of after the loop so it gets added to the database in the same order
			}
			#endregion

			#region Ownership
			if(iTable >= arrTableInitSpecs.Length)
				return;
			
	//		ctx.Dispose();
	//		ctx = new dal.LekEntities(CONN);
	//		var strm = from e in ctx.Ownership select e;
	//		dal.Ownership dao = strm.FirstOrDefault();

			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "Ownership")
			    throw new Exception("Expected Ownership, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.Ownership o = new dal.Ownership();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
			    int iNWAccntID		= lstNWAccnts[		s.Int32.Parse(arrFieldSpecs[0])].ID;
				int iParticipantID = lstParticipants[	s.Int32.Parse(arrFieldSpecs[1])].ID;
				Helper.EnsureFK(o.NWAccntReference, ctx, iNWAccntID);
				Helper.EnsureFK(o.ParticipantReference, ctx, iParticipantID);
				o.Shares		= s.Int32.Parse(arrFieldSpecs[2]);
			    ctx.AddToOwnership(o);
			}
			ctx.SaveChanges();
			#endregion

			#region Post
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "Post")
			    throw new Exception("Expected Post, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.Post o = new dal.Post();
			    o.Instant = u.C.FromStandardTime(strRecordSpec);
			    ctx.AddToPost(o);
				lstPosts.Add(o);
			}
			ctx.SaveChanges();
			#endregion

			#region Transaction
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "Transaction")
			    throw new Exception("Expected Transaction, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.Transaction o = new dal.Transaction();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
				int iPostIndex;
				if(int.TryParse(									arrFieldSpecs[0]	, out iPostIndex))
					Helper.EnsureFK(o.PostReference, ctx, lstPosts[iPostIndex].ID);
				else
					Helper.EnsureFK(o.PostReference, ctx, null);
				int iParticipantID = lstParticipants[	s.Int32.Parse(	arrFieldSpecs[1]	)].ID;
				Helper.EnsureFK(o.ParticipantReference, ctx, iParticipantID);
				o.Descrip =											arrFieldSpecs[2]	;
			    o.Instant = u.C.FromStandardTime(					arrFieldSpecs[3]	);
			    ctx.AddToTransaction(o);
				lstTransactions.Add(o);
				
				//EF doesn't necessarily add them in the same order that I add them,
				//unless we save each time.
				ctx.SaveChanges();
			}
		
		//  see above
		//	ctx.SaveChanges();

			#endregion

			#region Item
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "Item")
			    throw new Exception("Expected Item, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.Item o = new dal.Item();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
				int iTransactionID		=  lstTransactions[		s.Int32.Parse(	arrFieldSpecs[0]	)].ID;
				int iDltAllocAccntID	=  lstDltAllocAccnts[	s.Int32.Parse(	arrFieldSpecs[1]	)].ID;
				Helper.EnsureFK(o.TransactionReference, ctx, iTransactionID);
				Helper.EnsureFK(o.DltAllocAccntReference, ctx, iDltAllocAccntID);
				o.Descrip =													arrFieldSpecs[2]	;
			    ctx.AddToItem(o);
				lstItems.Add(o);
				
				//EF won't necessarily add them in the same order unless I SaveChanges for each one.
				ctx.SaveChanges();
			}
		//	ctx.SaveChanges();
			#endregion

			#region DltAlloc
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "DltAlloc")
			    throw new Exception("Expected DltAlloc, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.DltAlloc o = new dal.DltAlloc();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
				int iItemID			=  lstItems[			s.Int32.Parse(	arrFieldSpecs[0]	)].ID;
				int iParticipantID		=  lstParticipants[		s.Int32.Parse(	arrFieldSpecs[1]	)].ID;
				Helper.EnsureFK(o.ItemReference, ctx, iItemID);
				Helper.EnsureFK(o.ParticipantReference, ctx, iParticipantID);
				o.Amount			=						s.Int32.Parse(	arrFieldSpecs[2]	);
			    ctx.AddToDltAlloc(o);
			}
			ctx.SaveChanges();
			#endregion

			#region NWAccntDlt
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "NWAccntDlt")
			    throw new Exception("Expected NWAccntDlt, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.NWAccntDlt o = new dal.NWAccntDlt();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
				int iTransactionID		=  lstTransactions[		s.Int32.Parse(	arrFieldSpecs[0]	)].ID;
				int iNWAccntID			=  lstNWAccnts[			s.Int32.Parse(	arrFieldSpecs[1]	)].ID;
				Helper.EnsureFK(o.TransactionReference, ctx, iTransactionID);
				Helper.EnsureFK(o.NWAccntReference, ctx, iNWAccntID);
				o.Amount			=						s.Int32.Parse(	arrFieldSpecs[2]	);
			    ctx.AddToNWAccntDlt(o);
			}
			ctx.SaveChanges();
			#endregion

			#region WashDlt
			if(iTable >= arrTableInitSpecs.Length)
				return;
			strRecordSpecs = arrTableInitSpecs[iTable++];
			arrRecordSpecs = strRecordSpecs.Split('\n');
			if(arrRecordSpecs[0] != "WashDlt")
			    throw new Exception("Expected WashDlt, but got " + arrRecordSpecs[0]);
			for(int i=1; i<arrRecordSpecs.Length; i++)
			{
				string strRecordSpec = arrRecordSpecs[i];
				if(string.IsNullOrEmpty(strRecordSpec))
					continue;
			    dal.WashDlt o = new dal.WashDlt();
				string[] arrFieldSpecs = strRecordSpec.Split(',');
				int iTransactionID		=  lstTransactions[		s.Int32.Parse(	arrFieldSpecs[0]	)].ID;
				int iParticipantID		=  lstParticipants[		s.Int32.Parse(	arrFieldSpecs[1]	)].ID;
				Helper.EnsureFK(o.TransactionReference, ctx, iTransactionID);
				Helper.EnsureFK(o.ParticipantReference, ctx, iParticipantID);
				o.Amount			=						s.Int32.Parse(	arrFieldSpecs[2]	);
			    ctx.AddToWashDlt(o);
			}
			ctx.SaveChanges();
			#endregion
	
		}	
		public void InitDatabase(string str)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				InitDatabase(str, ctx);
			}
		}
		#endregion
		
		#region GetParticipants
		DTO.Participant[] GetParticipants(dal.LekEntities ctx)
		{
			var strm = from e in ctx.Participant orderby e.ID select new {e.ID, e.Name};
            var lst = strm.ToList();
			List<DTO.Participant> lstParticipants =lst.ConvertAll(o=>new DTO.Participant(o.ID, o.Name));
			return lstParticipants.ToArray();
		}
		public DTO.Participant[] GetParticipants()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return GetParticipants(ctx);
			}
		}
		#endregion

		#region GetTwoWayDTOs
		#region CodeWindow 014
		public gt.Participant[] Get2WayParticipants()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				var strm =
					from e in ctx.Participant
					orderby e.Name
					select new {e.ID, e.timestamp, e.Name};

				//Entity Framework can't handle constructors with parameters
				//so the gt.Participants will  be created outside of EF
				var lst = strm.ToList();
				IEnumerable<gt.Participant> strmParticipants = lst.Select(
					e=>new gt.Participant(e.ID, new gt.RowVersion(e.timestamp), e.Name)
				);
				
				return strmParticipants.ToArray();
			}
		}
		#endregion
		public gt.NWAccnt[] Get2WayNWAccnts()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				var strm =
					from e in ctx.NWAccnt
					orderby e.Name
					select new {e.ID, e.timestamp, e.Name, e.Descrip, e.Budgeted};
				
				//Entity Framework can't handle constructors with parameters
				//so the gt.NWAccnt will  be created outside of EF
				var lst = strm.ToList();
				IEnumerable<gt.NWAccnt> strmNWAccnts = lst.Select(
					e=>new gt.NWAccnt(e.ID, new gt.RowVersion(e.timestamp), e.Name, e.Descrip, e.Budgeted)
				);

				return strmNWAccnts.ToArray();
			}
		}
		public gt.DltAllocAccnt[] Get2WayDltAllocAccnts()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				var strm =
					from e in ctx.DltAllocAccnt
					orderby e.Name
					select new {e.ID, e.timestamp, e.Name, e.Descrip, e.Budgeted};

				//Entity Framework can't handle constructors with parameters
				//so the gt.DltAllocAccnt will  be created outside of EF
				var lst = strm.ToList();
				IEnumerable<gt.DltAllocAccnt> strmDltAllocAccnts = lst.Select(
					e=>new gt.DltAllocAccnt(e.ID, new gt.RowVersion(e.timestamp), e.Name, e.Descrip, e.Budgeted)
				);
				
				return strmDltAllocAccnts.ToArray();
			}
		}
		#endregion

		#region GetCache
		DTO.Cache GetCache(dal.LekEntities ctx)
		{
			var strmDltAllocAccnts	= from eDltAllocAccnt	in ctx.DltAllocAccnt.ToList()	orderby eDltAllocAccnt.Name select new DTO.Cache.DltAllocAccnt(	eDltAllocAccnt.ID, eDltAllocAccnt.Budgeted, eDltAllocAccnt.Name);
			var strmNWAccnts		= from eNWAccnt			in ctx.NWAccnt.ToList()			orderby eNWAccnt.Name		select new DTO.Cache.NWAccnt(		eNWAccnt.ID, eNWAccnt.Budgeted, eNWAccnt.Name);
			var strmOwnerships		= from eOwnership		in ctx.Ownership.ToList()									select new DTO.Cache.Ownership(		Helper.GetFK(eOwnership.NWAccntReference).Value, Helper.GetFK(eOwnership.ParticipantReference).Value, eOwnership.Shares);

			return new DTO.Cache(
				new u.ROArray<DTO.Cache.NWAccnt			>(strmNWAccnts		.ToArray()),
				new u.ROArray<DTO.Cache.DltAllocAccnt	>(strmDltAllocAccnts.ToArray()),
				new u.ROArray<DTO.Cache.Ownership		>(strmOwnerships	.ToArray()));
		}
		public DTO.Cache GetCache()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				return GetCache(ctx);
			}
		}
		#endregion

		
		#region Update DTOs
		void UpdateVerySimpleDTOs<TDTO,TDAL>(
			TDTO[] arr, 
			Func<TDAL> CreateNewDAL,
			Action<TDTO, TDAL> InitDALForExistingEntity,
			Action<TDTO, TDAL> UpdateDAL,
			Action<dal.LekEntities, TDAL> AddObjectDel,
			Action<dal.LekEntities, TDAL> UpdateObjectDel)
			where TDTO : gt.VerySimpleTwoWayDTO
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				foreach (TDTO o in arr)
				{
					TDAL e = CreateNewDAL();
					if (o.New)
					{
						UpdateDAL(o, e);
						AddObjectDel(ctx, e);
					}
					else if (o.Modified)
					{
						InitDALForExistingEntity(o, e);
						UpdateDAL(o, e);
						UpdateObjectDel(ctx, e);
					}
				}
				try
				{
					ctx.SaveChanges();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(TDAL).Name);
				}
			}
		}
		#region CodeWindow 026 (normalized)
		public void UpdateParticipants(gt.Participant[] arr)
		{
			string strQualifiedEntitySetName = typeof(dal.LekEntities).Name + "." + typeof(dal.Participant).Name;

			UpdateVerySimpleDTOs<gt.Participant, dal.Participant>(
				arr,
				() => new dal.Participant(),
				(o, e) => {e.ID = o.ID.Value; e.timestamp = Helper.CreateORMRowVersion(o.GetRowVersion()); e.EntityKey = Helper.CreateEntityKey(e.ID, strQualifiedEntitySetName);},
				(o, e) => {e.Name = o.Name;},
				(ctx, e) => ctx.AddToParticipant(e),
				(ctx, e) => {ctx.Attach(e); Helper.SetAllPropsAsModified(ctx, e);}
			);
		}
		#endregion
		public void UpdateNWAccnts(gt.NWAccnt[] arr)
		{
			string strQualifiedEntitySetName = typeof(dal.LekEntities).Name + "." + typeof(dal.NWAccnt).Name;

			UpdateVerySimpleDTOs<gt.NWAccnt, dal.NWAccnt>(
				arr,
				() => new dal.NWAccnt(),
				(o, e) => { e.ID = o.ID.Value; e.timestamp = Helper.CreateORMRowVersion(o.GetRowVersion()); e.EntityKey = Helper.CreateEntityKey(e.ID, strQualifiedEntitySetName);},
				(o, e) => { e.Name = o.Name; e.Descrip = o.Descrip; e.Budgeted = o.Budgeted;},
				(ctx, e) => ctx.AddToNWAccnt(e),
				(ctx, e) => {ctx.Attach(e); Helper.SetAllPropsAsModified(ctx, e);}
			);
		}
		public void UpdateDltAllocAccnts(gt.DltAllocAccnt[] arr)
		{
			string strQualifiedEntitySetName = typeof(dal.LekEntities).Name + "." + typeof(dal.DltAllocAccnt).Name;

			UpdateVerySimpleDTOs<gt.DltAllocAccnt, dal.DltAllocAccnt>(
				arr,
				() => new dal.DltAllocAccnt(),
				(o, e) => { e.ID = o.ID.Value; e.timestamp = Helper.CreateORMRowVersion(o.GetRowVersion()); e.EntityKey = Helper.CreateEntityKey(e.ID, strQualifiedEntitySetName);},
				(o, e) => { e.Name = o.Name; e.Descrip = o.Descrip; e.Budgeted = o.Budgeted;},
				(ctx, e) => ctx.AddToDltAllocAccnt(e),
				(ctx, e) => {ctx.Attach(e); Helper.SetAllPropsAsModified(ctx, e);}
			);
		}
		public void UpdateOwnerships(DTO.Ownership[] arr)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				foreach (DTO.Ownership dto in arr)
				{
					var strm = from e in ctx.Ownership where e.NWAccnt.ID == dto.NWAccntID where e.Participant.ID == dto.ParticipantID select e;
					dal.Ownership dao = strm.FirstOrDefault();
					if (dao == null)
					{
						dao = new dal.Ownership();
						Helper.EnsureFK(dao.ParticipantReference, ctx, dto.ParticipantID);
						Helper.EnsureFK(dao.NWAccntReference, ctx, dto.NWAccntID);
						dao.Shares = dto.Share;
						ctx.AddToOwnership(dao);
					}
					else
						dao.Shares = dto.Share;
				}
				ctx.SaveChanges();
			}
		}
		#endregion

		#region ITransComposit and AppendWhereClauses
		
		interface ITransComposit
		{
		    dal.Transaction eTransaction {get;}
		}
		class WashDltJoinedToTrans : ITransComposit
		{
		    public dal.WashDlt eWashDlt {get; set;}
		    public dal.Transaction eTransaction {get; set;}
		}
		class NWAccntDltJoinedToTrans : ITransComposit
		{
		    public dal.NWAccntDlt eNWAccntDlt {get; set;}
		    public dal.Transaction eTransaction {get; set;}
		}
		class ItemJoinedToTrans : ITransComposit
		{
		    public dal.Item eItem {get; set;}
		    public dal.Transaction eTransaction {get; set;}
		}
		class DltAllocJoinedToItemJoinedToTrans : ITransComposit
		{
		    public dal.DltAlloc eDltAlloc {get; set;}
		    public dal.Item eItem {get; set;}
		    public dal.Transaction eTransaction {get; set;}
		}
		class TransactionWrapper : ITransComposit
		{
		    public dal.Transaction eTransaction {get; set;}
		}
		class DltAllocJoinedToTransaction : ITransComposit
		{
		    public dal.DltAlloc eDltAlloc {get; set;}
		    public dal.Transaction eTransaction {get; set;}
		}
		class TransItem : ITransComposit
		{
			public dal.Transaction eTransaction{get; set;}
			public dal.Item eItem { get; set; }
			public string DltAllocAccntName { get; set; }
			public IEnumerable<dal.DltAlloc> DltAllocs{ get; set; }
		}

		DTO.TransPred ConvertIfConvPred(DTO.TransPred aTransPred)
		{
			if(aTransPred is DTO.OptionalDateRangeTransPred)
			{
				DTO.OptionalDateRangeTransPred theTransPred = (DTO.OptionalDateRangeTransPred)aTransPred;
				if(theTransPred.Before.HasValue)
				{
					if(theTransPred.OnOrAfter.HasValue) return new DTO.DateRangeTransPred(theTransPred.OnOrAfter.Value,	theTransPred.Before.Value	);
					else								return new DTO.BeforeTransPred(									theTransPred.Before.Value	);
				}
				else
				{
					if(theTransPred.OnOrAfter.HasValue) return new DTO.OnOrAfterTransPred(theTransPred.OnOrAfter.Value								);
					else								return null;
				}
			}
			return aTransPred;
		}

//	I WISH
#if false
		#region CodeWindow 047
		IQueryable<T>									AppendWhereClauses<T>(	IQueryable<T>									query, DTO.TransPred aTransPred) where T : ITransComposit
		{
		    aTransPred = ConvertIfConvPred(aTransPred);
			
		    if(		aTransPred == null	)				{;}
	
		    else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
		    else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
		    else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
		                                                    query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
		    else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
		    else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
		                                                    query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
		    else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID  ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
		    else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID  <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
		                                                    query = from composite in query where  composite.eTransaction.Post.ID  >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
		    else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID  <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
		    else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post == null 
																								|| composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
		    else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
		    else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

		    else throw new Exception();

		    return query;
		}
		#endregion
#else
		#region CodeWindow 048
		IQueryable<WashDltJoinedToTrans>				AppendWhereClauses(		IQueryable<WashDltJoinedToTrans>				query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		IQueryable<NWAccntDltJoinedToTrans>				AppendWhereClauses(		IQueryable<NWAccntDltJoinedToTrans>				query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		IQueryable<ItemJoinedToTrans>					AppendWhereClauses(		IQueryable<ItemJoinedToTrans>					query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		IQueryable<DltAllocJoinedToItemJoinedToTrans>	AppendWhereClauses(		IQueryable<DltAllocJoinedToItemJoinedToTrans>	query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		IQueryable<TransactionWrapper>					AppendWhereClauses(		IQueryable<TransactionWrapper>					query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		#endregion
		IQueryable<DltAllocJoinedToTransaction>			AppendWhereClauses(		IQueryable<DltAllocJoinedToTransaction>			query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
		IQueryable<TransItem>							AppendWhereClauses(		IQueryable<TransItem>							query, DTO.TransPred aTransPred)// where T : ITransComposit
		{
			aTransPred = ConvertIfConvPred(aTransPred);
			
			if(		aTransPred == null	)				{;}
	
			else if(aTransPred is DTO.BeforeTransPred	)	query = from composite in query where  composite.eTransaction.Instant < ((DTO.BeforeTransPred		)aTransPred).Before		select composite;
			else if(aTransPred is DTO.OnOrAfterTransPred)	query = from composite in query where  composite.eTransaction.Instant >=((DTO.OnOrAfterTransPred	)aTransPred).OnOrAfter	select composite;
			else if(aTransPred is DTO.DateRangeTransPred){	query = from composite in query where  composite.eTransaction.Instant < ((DTO.DateRangeTransPred	)aTransPred).Before		select composite;
															query = from composite in query where  composite.eTransaction.Instant >=((DTO.DateRangeTransPred	)aTransPred).OnOrAfter	select composite;}
			else if(aTransPred is DTO.IDTransPred		)	query = from composite in query where  composite.eTransaction.ID	  ==((DTO.IDTransPred			)aTransPred).ID			select composite;
			else if(aTransPred is DTO.IDRangeTransPred	){  query = from composite in query where  composite.eTransaction.ID      <=((DTO.IDRangeTransPred		)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.ID	  >=((DTO.IDRangeTransPred		)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.PostIDTransPred	)	query = from composite in query where  composite.eTransaction.Post.ID ==((DTO.PostIDTransPred		)aTransPred).ID			select composite;
			else if(aTransPred is DTO.PostIDRangeTransPred){query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.PostIDRangeTransPred	)aTransPred).LargestID  select composite;
															query = from composite in query where  composite.eTransaction.Post.ID >=((DTO.PostIDRangeTransPred	)aTransPred).SmallestID select composite;}
			else if(aTransPred is DTO.MaxPostIDTransPred)	query = from composite in query where  composite.eTransaction.Post.ID <=((DTO.MaxPostIDTransPred	)aTransPred).MaxID		select composite;
			else if(aTransPred is DTO.MinPostIDTransPred)	query = from composite in query where (composite.eTransaction.Post	  == null 
																								 ||composite.eTransaction.Post.ID  >=((DTO.MinPostIDTransPred	)aTransPred).MinID)		select composite;
			else if(aTransPred is DTO.PostedTransPred	)	query = from composite in query where  composite.eTransaction.Post    != null												select composite;
			else if(aTransPred is DTO.UnPostedTransPred	)   query = from composite in query where  composite.eTransaction.Post    == null												select composite;

			else throw new Exception();

			return query;
		}
#endif
		#endregion

		#region Get or Verify Transactions
		#region Low Level GetTransactions
		#region GetDAOsForTransactions CodeWindow 051
		IList<dal.WashDlt>		GetWashDltDAOsForTransactions(		dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = 
					from eWashDlt		in ctx.WashDlt
					select new WashDltJoinedToTrans{eWashDlt=eWashDlt, eTransaction=eWashDlt.Transaction};
			
			query = AppendWhereClauses(query, aTransPred);
			
			return (
				from eComposite in query 
				orderby eComposite.eTransaction.Instant descending, eComposite.eTransaction.ID descending, eComposite.eWashDlt.Participant.ID ascending 
				select eComposite.eWashDlt).ToList();
		}
		IList<dal.NWAccntDlt>	GetNWAccntDltDAOsForTransactions(	dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = 
					from eNWAccntDlt	in ctx.NWAccntDlt
					select new NWAccntDltJoinedToTrans{eNWAccntDlt=eNWAccntDlt, eTransaction=eNWAccntDlt.Transaction};
			
			query = AppendWhereClauses(query, aTransPred);
			
			return (
				from eComposite in query 
				orderby eComposite.eTransaction.Instant descending, eComposite.eTransaction.ID descending, eComposite.eNWAccntDlt.NWAccnt.ID ascending
				select eComposite.eNWAccntDlt).ToList();
		}
		IList<dal.Item>			GetItemDAOsForTransactions(			dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = 
					from eItem			in ctx.Item
					select new ItemJoinedToTrans{eItem=eItem, eTransaction=eItem.Transaction};
			
			query = AppendWhereClauses(query, aTransPred);

			return (
				from eComposite in query 
				orderby eComposite.eTransaction.Instant descending, eComposite.eTransaction.ID descending, eComposite.eItem.ID ascending 
				select eComposite.eItem).ToList();
		}
		IList<dal.DltAlloc>		GetDltAllocDAOsForTransactions(		dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = 
					from eDltAlloc		in ctx.DltAlloc
					select new DltAllocJoinedToItemJoinedToTrans{eDltAlloc=eDltAlloc, eItem=eDltAlloc.Item, eTransaction=eDltAlloc.Item.Transaction};
			
			query = AppendWhereClauses(query, aTransPred);

			return (
				from eComposite in query 
				orderby eComposite.eTransaction.Instant descending, eComposite.eTransaction.ID descending, eComposite.eItem.ID ascending, eComposite.eDltAlloc.Participant.ID ascending
				select eComposite.eDltAlloc).ToList();
			
		}
		IList<dal.Transaction>	GetTransactionDAOsForTransactions(	dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = from dal.Transaction eTransaction in ctx.Transaction select new TransactionWrapper{eTransaction=eTransaction};
			
			query = AppendWhereClauses(query, aTransPred);
		
			return (from eWrapper in query orderby eWrapper.eTransaction.Instant descending, eWrapper.eTransaction.ID descending select eWrapper.eTransaction).ToList();
		}
		#endregion

		IList<T> GetApplicableDAOs<T>(IEnumerator<T> e, Func<T, bool> PredicateDelegate, ref bool b)
		{
			IList<T> lst =new List<T>();
		    while(true)
		    {
		        if(!b)
		            break;
				if(!PredicateDelegate(e.Current))
					break;
		        lst.Add(e.Current);
		        b = e.MoveNext();
		    }
			return lst;
		}
		du.TransactionNWAccntDltUpdate CreateTransactionNWAccntDltUpdate(int[] arrParticipantIDs, Dictionary<int, dal.NWAccnt> dictNWAccntsByID, IList<dal.NWAccntDlt> lstNWAccntDlts)
		{
			du.TransactionNWAccntDltUpdate aAccntUpdate = new du.TransactionNWAccntDltUpdate(arrParticipantIDs);
			foreach (dal.NWAccntDlt aNWAccntDlt in lstNWAccntDlts)
			{
				int iNWAccntID = Helper.GetFK(aNWAccntDlt.NWAccntReference).Value;
				aAccntUpdate.AddNWAccntDlt(iNWAccntID, dictNWAccntsByID[iNWAccntID].Budgeted, aNWAccntDlt.Amount);
			}
			return aAccntUpdate;
		}
		du.TransactionItemUpdate CreateTransactionItemUpdate(du.Participants aParticipants, Dictionary<int, dal.DltAllocAccnt> dictDltAllocAccntsByID, IList<dal.Item> lstItems, IList<dal.DltAlloc>[] arrOfListsOfDltAllocs)
		{
			if(lstItems.Count != arrOfListsOfDltAllocs.Length)
				throw new Exception();
			int[] arrParticipantIDs = aParticipants.GetArrayOfIDs();
			du.TransactionItemUpdate update = new du.TransactionItemUpdate(arrParticipantIDs);
			
			for(int i=0; i<lstItems.Count; i++)
			{
				dal.Item aItem = lstItems[i];
				IList<dal.DltAlloc> lstDltAllocs = arrOfListsOfDltAllocs[i];
				int[] arrParticipantAmounts = new int[aParticipants.Count];
				foreach (dal.DltAlloc aDltAlloc in lstDltAllocs)
				{
					int iParticipantID = Helper.GetFK(aDltAlloc.ParticipantReference).Value;
					int iIndex = aParticipants.IndexFromID(iParticipantID);
					arrParticipantAmounts[iIndex] = aDltAlloc.Amount;
				}
				update.AddItem(aItem.ID, aItem.Descrip, Helper.GetFK(aItem.DltAllocAccntReference).Value, dictDltAllocAccntsByID[Helper.GetFK(aItem.DltAllocAccntReference).Value].Budgeted, new u.ROArray<int>(arrParticipantAmounts));
			}
			return update;
		}
		int[] CreateArrayOfWashAmounts(du.Participants aParticipants, IList<dal.WashDlt> lstWashDlts)
		{
			int[] arrParticipantAmounts = new int[aParticipants.Count];
			foreach (dal.WashDlt aWashDlt in lstWashDlts)
			{
				int iParticipantID = Helper.GetFK(aWashDlt.ParticipantReference).Value;
				int iIndex = aParticipants.IndexFromID(iParticipantID);
				arrParticipantAmounts[iIndex] = aWashDlt.Amount;
			}
			return arrParticipantAmounts;
		}
		IList<du.ITransaction> CreateTransactions(
			du.Participants		  aParticipants		,
			Dictionary<int, dal.NWAccnt> dictNWAccntsByID,
			Dictionary<int, dal.DltAllocAccnt> dictDltAllocAccntsByID,
			IList<dal.WashDlt		> lstWashDlts		,
			IList<dal.NWAccntDlt	> lstNWAccntDlts	,
			IList<dal.Item			> lstItems			,
			IList<dal.DltAlloc		> lstDltAllocs		,
			IList<dal.Transaction	> lstTransactions	,
			IList<int> lstIDs,
			bool bJustVerify)
		{
			int[] arrParticipantIDs = aParticipants.GetArrayOfIDs();

			IEnumerator<dal.WashDlt		> eWashDlt		= lstWashDlts	.GetEnumerator();
			IEnumerator<dal.NWAccntDlt	> eNWAccntDlt	= lstNWAccntDlts.GetEnumerator();
			IEnumerator<dal.Item		> eItem			= lstItems		.GetEnumerator();
			IEnumerator<dal.DltAlloc	> eDltAlloc		= lstDltAllocs	.GetEnumerator();

			IEnumerator<int> eID = null;
			bool bID = false;

			bool bWashDlt	=eWashDlt	.MoveNext();
			bool bNWAccntDlt=eNWAccntDlt.MoveNext();
			bool bItem		=eItem		.MoveNext();
			bool bDltAlloc	=eDltAlloc	.MoveNext();

			if (lstIDs != null)
			{
				eID = lstIDs.GetEnumerator();
				bID = eID.MoveNext();
			}

			IList<du.ITransaction> lst = new List<du.ITransaction>();
			foreach (dal.Transaction aTransaction in lstTransactions)
			{
				IList<dal.Item		> lstTranItems		=GetApplicableDAOs<dal.Item			>(eItem,		(o)=>Helper.GetFK(o.TransactionReference)==aTransaction.ID, ref bItem		);
				IList<dal.WashDlt	> lstTranWashDlts	=GetApplicableDAOs<dal.WashDlt		>(eWashDlt,		(o)=>Helper.GetFK(o.TransactionReference)==aTransaction.ID, ref bWashDlt	);
				IList<dal.NWAccntDlt> lstTranNWAccntDlts=GetApplicableDAOs<dal.NWAccntDlt	>(eNWAccntDlt,	(o)=>Helper.GetFK(o.TransactionReference)==aTransaction.ID, ref bNWAccntDlt	);
				
				IList<dal.DltAlloc>[] arrOfListsOfDltAllocs = new IList<dal.DltAlloc>[lstTranItems.Count];
				for(int i=0; i< lstTranItems.Count; i++)
				{
					dal.Item aItem = lstTranItems[i];
					arrOfListsOfDltAllocs[i]	=GetApplicableDAOs<dal.DltAlloc	>(eDltAlloc,	(o)=>o.Item.ID==aItem.ID, ref bDltAlloc	);
				}

				if (eID != null)
				{
					if(!bID)
						break;
					if(aTransaction.ID != eID.Current)
						continue;
	
					bID = eID.MoveNext();
				}

				du.TransactionNWAccntDltUpdate aTransactionNWAccntDltUpdate= CreateTransactionNWAccntDltUpdate(arrParticipantIDs,	dictNWAccntsByID,	lstTranNWAccntDlts							);
				du.TransactionItemUpdate		aTransactionItemUpdate		= CreateTransactionItemUpdate(		aParticipants,		dictDltAllocAccntsByID,		lstTranItems,		arrOfListsOfDltAllocs	);
				int[]							arrParticipantAmounts		= CreateArrayOfWashAmounts(			aParticipants,		lstTranWashDlts								);

				du.ITransaction dmnT = 
					du.TransactionFactory.Create(
						aTransaction.ID, 
						new gt.RowVersion(aTransaction.timestamp),
						Helper.GetFK(aTransaction.PostReference), 
						Helper.GetFK(aTransaction.ParticipantReference), 
						aTransaction.Descrip,
						aTransaction.Instant, 
						arrParticipantIDs, 
						aTransactionNWAccntDltUpdate, 
						aTransactionItemUpdate, 
						arrParticipantAmounts);

				if(!bJustVerify)
					lst.Add(dmnT);
			}

			return lst;
		}
		Dictionary<int, dal.NWAccnt> GetDictionaryOfNWAccnts(dal.LekEntities ctx)
		{
			Dictionary<int, dal.NWAccnt> dict= new Dictionary<int,dal.NWAccnt>();
			foreach(dal.NWAccnt o in ctx.NWAccnt)
			{
				dict.Add(o.ID, o);
			}
			return dict;
		}
		Dictionary<int, dal.DltAllocAccnt> GetDictionaryOfDltAllocAccnts(dal.LekEntities ctx)
		{
			Dictionary<int, dal.DltAllocAccnt> dict= new Dictionary<int,dal.DltAllocAccnt>();
			foreach(dal.DltAllocAccnt o in ctx.DltAllocAccnt)
			{
				dict.Add(o.ID, o);
			}
			return dict;
		}
		IList<du.ITransaction> GetTransactions(dal.LekEntities ctx, DTO.TransPred aTransPred, IList<int> lstIDs, bool bJustVerify)
		{
			du.Participants aParticipants = CreateDomainParticipants(GetParticipants(ctx));
			return CreateTransactions(
				aParticipants,
				GetDictionaryOfNWAccnts(			ctx),
				GetDictionaryOfDltAllocAccnts(		ctx),
				GetWashDltDAOsForTransactions(		ctx, aTransPred),
				GetNWAccntDltDAOsForTransactions(	ctx, aTransPred),
				GetItemDAOsForTransactions(			ctx, aTransPred),
				GetDltAllocDAOsForTransactions(		ctx, aTransPred),
				GetTransactionDAOsForTransactions(	ctx, aTransPred),
				lstIDs,
				bJustVerify);
		}
		IList<int> GetTransactionIDs(dal.LekEntities ctx, DTO.TransPred aTransPred,	int iParticipantID		)
		{
		//	du.Participants aParticipants = this.CreateDomainParticipants(GetParticipants(ctx));

			var strmNWAccntIDsForParticipant = 
				from eOwnership in ctx.Ownership 
				where eOwnership.Participant.ID == iParticipantID
				where eOwnership.Shares > 0 
				select eOwnership.NWAccnt.ID;
			var lstNWAccntIDsForParticipant = strmNWAccntIDsForParticipant.ToList();

			var query0 = 
					from eNWAccntDlt	in ctx.NWAccntDlt
					select new NWAccntDltJoinedToTrans{eNWAccntDlt=eNWAccntDlt, eTransaction=eNWAccntDlt.Transaction};
			query0 = AppendWhereClauses(query0, aTransPred);
		
		//EF can't handle contains
		//	var strm0 = from composite in query0 where strmNWAccntIDsForParticipant.Contains(composite.eNWAccntDlt.NWAccntID) select composite.eTransaction;
			var lst0 = query0.ToList();
			var strm0 = from composite in lst0 where lstNWAccntIDsForParticipant.Contains(Helper.GetFK(composite.eNWAccntDlt.NWAccntReference).Value) select composite.eTransaction;



			var query1 = 
					from eWashDlt		in ctx.WashDlt
					select new WashDltJoinedToTrans{eWashDlt=eWashDlt, eTransaction=eWashDlt.Transaction};
			query1 = AppendWhereClauses(query1, aTransPred);
			var strm1 = from composite in query1 where composite.eWashDlt.Participant.ID == iParticipantID select composite.eTransaction;

			var query2 = 
					from eDltAlloc		in ctx.DltAlloc
					select new DltAllocJoinedToTransaction{eDltAlloc=eDltAlloc, eTransaction=eDltAlloc.Item.Transaction};
			query2 = AppendWhereClauses(query2, aTransPred);
			var strm2 = from composite in query2 where composite.eDltAlloc.Participant.ID == iParticipantID select composite.eTransaction;

			//since strm0 is now local, strm1 and strm2 must be as well.
			//union automatically eliminates duplicates including those in the input streams
			//we do rely on either the default equality comparer utilizing IDs, or on Linq To Entities returning the same object in distinct streams when the IDs are the same
			var strm = from e in strm0.Union(strm1.ToList().Union(strm2.ToList())) 
				   orderby e.Instant descending, e.ID descending
				   select e.ID;

			return strm.ToList();
		}
		#endregion
		IList<du.ITransaction> LLGetTransactions(DTO.TransPred aTransPred, int? iParticipantID)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				IList<int> lstIDs = null;
				if(iParticipantID.HasValue)
					lstIDs = GetTransactionIDs(ctx, aTransPred, iParticipantID.Value);
				IList<du.ITransaction> lst= GetTransactions(ctx, aTransPred, lstIDs, /*bJustVerify=*/false);
				return lst;
			}
		}
		public DTO.Transaction[] GetTransactions(DTO.TransPred aTransPred, int? iParticipantID)
		{
			IList<du.ITransaction> lst = LLGetTransactions(aTransPred, iParticipantID);
			return lst.Select(o=>du.TransactionFactory.CreateSerializableTransaction(o)).ToArray();
		}
		du.ITransaction LLGetTransaction(int iTransactionID)
		{
			IList<du.ITransaction> lst= LLGetTransactions(new DTO.IDTransPred(iTransactionID), null);
			return lst.SingleOrDefault();
		}
		public DTO.Transaction GetTransaction(int iTransactionID)
		{
			du.ITransaction dmnT = LLGetTransaction(iTransactionID);
			if(dmnT==null)
				return null;
			return du.TransactionFactory.CreateSerializableTransaction(dmnT);
		}
		public void VerifyAllTransactions()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				GetTransactions(ctx, null, null, /*bJustVerify=*/true);
			}
		}
		#endregion

		#region GetItemsInTransactions
		IList<DTO.ItemEx> GetItemsFromStream(IQueryable<TransItem> strm, dal.LekEntities ctx)
		{
			du.Participants aParticipants = this.CreateDomainParticipants(GetParticipants(ctx));
			IList<DTO.ItemEx> lst = new List<DTO.ItemEx>();
			foreach (TransItem aItemProj in strm)
			{
				string strParticipantName = null;
				if (Helper.GetFK(aItemProj.eTransaction.ParticipantReference).HasValue)
					strParticipantName = aParticipants.NameFromID(Helper.GetFK(aItemProj.eTransaction.ParticipantReference).Value);
				int[] arrAmounts = new int[aParticipants.Count];
				foreach (dal.DltAlloc aDltAlloc in aItemProj.DltAllocs)
				{
					int iParticipantID = Helper.GetFK(aDltAlloc.ParticipantReference).Value;
					int iIndex = aParticipants.IndexFromID(iParticipantID);
					arrAmounts[iIndex] = aDltAlloc.Amount;
				}
				DTO.ItemEx aItem = new DTO.ItemEx(
					aItemProj.eItem.ID									,
					Helper.GetFK(aItemProj.eTransaction.PostReference)	,
					aItemProj.eTransaction.ID							,
					new gt.RowVersion(aItemProj.eTransaction.timestamp) ,
					Helper.GetFK(aItemProj.eTransaction.ParticipantReference)	,
					strParticipantName									,
					aItemProj.eTransaction.Descrip						,
					aItemProj.eTransaction.Instant						,
					aItemProj.eItem.Descrip								,
					Helper.GetFK(aItemProj.eItem.DltAllocAccntReference),
					aItemProj.DltAllocAccntName							,
					new u.ROArray<int>(arrAmounts)						);

				lst.Add(aItem);
			}
			return lst;
		}
		public DTO.ItemEx[] GetItemsInTransactions(DTO.TransPred aTransPred)
		{
			s.DateTime dt = s.DateTime.Now.AddDays(-20);
			using (var ctx = new dal.LekEntities(CONN))
			{
				var query =
					from eItem in ctx.Item
					select new TransItem{ eTransaction = eItem.Transaction, eItem = eItem, DltAllocAccntName = eItem.DltAllocAccnt.Name, DltAllocs = eItem.DltAlloc };
				
				query = AppendWhereClauses(query, aTransPred);

				query = 
					from eComposit in query 
					orderby eComposit.eTransaction.Instant descending, eComposit.eTransaction.ID descending
					select eComposit;

				return GetItemsFromStream(query, ctx).ToArray();
			}
		}
		#endregion

		#region GetSummaryOfTransactions
		int GetSumOfDltsForBudgetedNWAccnts(dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query =
				from eNWAccntDlt	in ctx.NWAccntDlt
			//	join eNWAccnt		in ctx.NWAccnt		on eNWAccntDlt.NWAccnt equals eNWAccnt
				join eTransaction	in ctx.Transaction  on eNWAccntDlt.Transaction equals eTransaction
				where eNWAccntDlt.NWAccnt.Budgeted == true
				select new NWAccntDltJoinedToTrans{eNWAccntDlt=eNWAccntDlt, eTransaction=eTransaction};

			query = AppendWhereClauses(query, aTransPred);

			return query.Sum(composit=>(int?)composit.eNWAccntDlt.Amount).GetValueOrDefault();
		}
		int GetSumOfDltsForBudgetedDltAllocs(dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query = 
				from eDltAlloc		in ctx.DltAlloc
				join eItem			in ctx.Item				on eDltAlloc.Item		equals eItem
			//	join eDltAllocAccnt in ctx.DltAllocAccnt	on eItem.DltAllocAccnt	equals eDltAllocAccnt
				join eTransaction	in ctx.Transaction		on eItem.Transaction	equals eTransaction
				where eItem.DltAllocAccnt.Budgeted == true
	            select new DltAllocJoinedToItemJoinedToTrans{eDltAlloc=eDltAlloc, eItem=eItem, eTransaction=eTransaction};
		
			query = AppendWhereClauses(query, aTransPred);

		//	var query2 = query.Select(eComposit=>eComposit.eDltAlloc.Amount);
		//	return query2.Sum();

			int? iSum = query.Sum(composit=>(int?)composit.eDltAlloc.Amount);
			return iSum.GetValueOrDefault();
		}
		DTO.NWAccntDltSum[] GetNWAccntDltSumsOfTransactions(dal.LekEntities ctx, DTO.TransPred aTransPred)
		{
			var query =
				from eNWAccntDlt in ctx.NWAccntDlt
				select new NWAccntDltJoinedToTrans{eNWAccntDlt=eNWAccntDlt, eTransaction=eNWAccntDlt.Transaction};
			
			query =AppendWhereClauses(query, aTransPred);

	//		var query2=
	//			from eComposite in query
	//			group eComposite by eComposite.eNWAccntDlt.NWAccntID into result
	//			select new si.NWAccntDltSum{NWAccntID=result.Key, Amount=result.Sum(o => o.eNWAccntDlt.Amount)};

			var query2=
				from eComposite in query
				group eComposite by new {eComposite.eNWAccntDlt.NWAccnt.ID, eComposite.eNWAccntDlt.NWAccnt.Budgeted} into result
		//		select new si.NWAccntDltSum(result.Key.NWAccntID, result.Key.Budgeted, result.Sum(o => o.eNWAccntDlt.Amount));
				orderby result.Key.ID
				select new {NWAccntID=result.Key.ID, Budgeted=result.Key.Budgeted, Amount=result.Sum(o => o.eNWAccntDlt.Amount)};

			return query2.ToList().Select(o=>new DTO.NWAccntDltSum(o.NWAccntID, o.Budgeted, o.Amount)).ToArray();
		}
		
		int[] CreateWashesFromGrouping(IList<IGrouping<int, dal.WashDlt>> results, du.Participants aParticipants)
		{
			int[] arrWashes = new int[aParticipants.Count];
			foreach(var result in results)
			{
				int i= aParticipants.IndexFromID(result.Key);
				if (arrWashes[i] != 0)
					throw new s.Exception("LinqToEF.cs:491");
				arrWashes[i] =result.Sum(o => o.Amount);
			}
			return arrWashes;
		}
		int[] GetParticipantWashesOfTransactions(dal.LekEntities ctx, DTO.TransPred aTransPred, du.Participants aParticipants)
		{
			var query =
				from eWashDlt in ctx.WashDlt
				select new WashDltJoinedToTrans{eWashDlt=eWashDlt, eTransaction=eWashDlt.Transaction};
			
			query = AppendWhereClauses(query, aTransPred);

			var query2 = 
				from eComposite in query
				group eComposite.eWashDlt by eComposite.eWashDlt.Participant.ID into result
				select result;// new { ParticipantID = result.Key, ParticpantAmount = result.Sum(o => o.Amount) };

			return CreateWashesFromGrouping(query2.ToList(), aParticipants);
		}

		class DltAllocForDltAllocAccnt
		{
		    public int DltAllocAccountID{get; set;}
		    public bool Budgeted{get; set;}
		    public int ParticipantID{get; set;}
			public int Amount{get; set;}
		}
		DTO.DltAllocSum[] CreateDltAllocSumsArrayFromGrouping(IList<DltAllocForDltAllocAccnt> lst, du.Participants aParticipants)
		{
			List<DTO.DltAllocSum> lstDltAllocSums = new List<DTO.DltAllocSum>();
			int iAccountID = -1;
			bool bBudgeted = false;
			int[] arrAmounts=null;
			foreach (DltAllocForDltAllocAccnt o in lst)
			{
				if(o.DltAllocAccountID != iAccountID)
				{
					if(arrAmounts !=null)
						lstDltAllocSums.Add(new DTO.DltAllocSum(iAccountID, bBudgeted, new u.ROArray<int>(arrAmounts)));
					arrAmounts = new int[aParticipants.Count];
					iAccountID = o.DltAllocAccountID;
					bBudgeted = o.Budgeted;
				}
				int i = aParticipants.IndexFromID(o.ParticipantID);
				if(arrAmounts[i] != 0)
					throw new s.Exception("ServiceEF.cs:1411");
				arrAmounts[i] = o.Amount;
			}
			if(arrAmounts !=null)
				lstDltAllocSums.Add(new DTO.DltAllocSum(iAccountID, bBudgeted, new u.ROArray<int>(arrAmounts)));

			return lstDltAllocSums.ToArray();
		}
		DTO.DltAllocSum[] GetDltAllocSumsOfTransactions(dal.LekEntities ctx, DTO.TransPred aTransPred, du.Participants aParticipants)
		{
	
			var query = 
				from eDltAlloc in ctx.DltAlloc
	            select new DltAllocJoinedToItemJoinedToTrans{eDltAlloc=eDltAlloc, eItem=eDltAlloc.Item, eTransaction=eDltAlloc.Item.Transaction};
		
			query = AppendWhereClauses(query, aTransPred);

			var query2=
				from eComposit in query
				group eComposit by new {DltAllocAccntID=eComposit.eItem.DltAllocAccnt.ID, ParticipantID=eComposit.eDltAlloc.Participant.ID, Budgeted=eComposit.eItem.DltAllocAccnt.Budgeted} into result
				orderby result.Key.DltAllocAccntID, result.Key.ParticipantID
				select new DltAllocForDltAllocAccnt{
					Amount				=result.Sum(o=>o.eDltAlloc.Amount), 
					DltAllocAccountID	=result.Key.DltAllocAccntID, 
					Budgeted			=result.Key.Budgeted,
					ParticipantID		=result.Key.ParticipantID};

			return CreateDltAllocSumsArrayFromGrouping(query2.ToList(), aParticipants);
		}
	
		DTO.BudgetDelta CreateBudgetDelta(
			int? iDays				,
			int iMonthlyBudgetAmount,
			int iBudgetedDltAllocs	,
			int iBudgetedNWAccntDlts)
		{
			int? iFundingDue = null;
			if(iDays.HasValue)
			{
				float ratio = iDays.Value/30F;
				iFundingDue = (int)(iMonthlyBudgetAmount*ratio);
			}
			return new DTO.BudgetDelta(
				iDays,
				iFundingDue,
				iBudgetedDltAllocs,
				iBudgetedNWAccntDlts);
		}
		public DTO.Summary GetSummaryOfTransactions(DTO.TransPred aTransPred, s.DateTime dtBudgetStartDate, int iMonthlyBudgetAmount)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				su.BudgetPredicateUtil aBudgetPredicateUtil = new su.BudgetPredicateUtil(new BudgetDataAccess(ctx));

				du.Participants aParticipants = this.CreateDomainParticipants(this.GetParticipants(ctx));
			//	DTO.Summary aSummary = new DTO.Summary();
				DTO.NWAccntDltSum[] arrNWAccntDltSums		= GetNWAccntDltSumsOfTransactions(		ctx, aTransPred);
				int[] arrParticipantWashes	= GetParticipantWashesOfTransactions(	ctx, aTransPred, aParticipants);
				DTO.DltAllocSum[] arrDltAllocSums		= GetDltAllocSumsOfTransactions(		ctx, aTransPred, aParticipants);
			
				DTO.BudgetDelta aBudgetDeltaForMatchedTransactions = CreateBudgetDelta(
					aBudgetPredicateUtil.GetDays(aTransPred),
					iMonthlyBudgetAmount,
					GetSumOfDltsForBudgetedDltAllocs(ctx, aTransPred),
					GetSumOfDltsForBudgetedNWAccnts(ctx, aTransPred));

				DTO.BudgetDelta aBudgetDeltaClippedFromStartDate = null;
				
				DTO.TransPred clip = aBudgetPredicateUtil.GetClippedTransPred(aTransPred, dtBudgetStartDate);
				if(clip!=null)
				{
					aBudgetDeltaClippedFromStartDate = CreateBudgetDelta(
						aBudgetPredicateUtil.GetDays(clip),
						iMonthlyBudgetAmount,
						GetSumOfDltsForBudgetedDltAllocs(ctx, clip),
						GetSumOfDltsForBudgetedNWAccnts(ctx, clip));

				//	s.Diagnostics.Trace.WriteLine("" + iFundingDue + " + " + iSumOfDltsForBudgetedDltAllocs + " - " + iSumOfDltsForBudgetedNWAccnts);
				//	aSummary.FundingDue = iFundingDue + iSumOfDltsForBudgetedDltAllocs - iSumOfDltsForBudgetedNWAccnts;
				}
				DTO.BudgetReport aBudgetReport = new DTO.BudgetReport(
					aBudgetDeltaClippedFromStartDate, 
					aBudgetDeltaForMatchedTransactions);
				
				return new DTO.Summary(
					new u.ROArray<DTO.NWAccntDltSum>(	arrNWAccntDltSums	), 
					new u.ROArray<DTO.DltAllocSum>(		arrDltAllocSums		), 
					new u.ROArray<int>(					arrParticipantWashes), 
					aBudgetReport);
			}
		}
		#endregion

		#region GetNWAccntDltsOfTransactions
		public DTO.NWAccntDltEx[] GetNWAccntDltsOfTransactions(int iNWAccntID, DTO.TransPred aTransPred)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{

				var query =
					from eNWAccntDlt in ctx.NWAccntDlt
					select new NWAccntDltJoinedToTrans{eNWAccntDlt=eNWAccntDlt,eTransaction=eNWAccntDlt.Transaction};
				
				query = AppendWhereClauses(query, aTransPred);

				var query2=
					from composit in query
					where composit.eNWAccntDlt.NWAccnt.ID == iNWAccntID
					orderby composit.eTransaction.Instant descending, composit.eTransaction.ID descending
			//		select new DTO.NWAccntDltEx{
					select new {
						TransID		=composit.eNWAccntDlt.Transaction.ID, 
						PostID		=(int?)composit.eTransaction.Post.ID, 
						TransDescrip=composit.eTransaction.Descrip, 
						TransInstant=composit.eTransaction.Instant, 
						Amount		=composit.eNWAccntDlt.Amount};

				return query2.ToList().Select(
					o=>new DTO.NWAccntDltEx(
						o.TransID, 
						o.PostID, 
						o.TransDescrip, 
						o.TransInstant, 
						o.Amount)
					).ToArray();
			}
		}
		#endregion

		#region GetDltAllocsOfTransactions
		DTO.DltAlloc[] CreateDltAllocsArrayFromGrouping(IList<DltAllocJoinedToItemJoinedToTrans> lst, du.Participants aParticipants)
		{
			List<DTO.DltAlloc> lstDltAllocs = new List<DTO.DltAlloc>();
			dal.Transaction oCurrentTrans=null;
			dal.Item oCurrentItem=null;
			int[] arrCurrentAmounts=null;
			foreach (DltAllocJoinedToItemJoinedToTrans aDltAllocJoinedToItemJoinedToTrans in lst)
			{
				if(oCurrentItem==null || oCurrentItem.ID != aDltAllocJoinedToItemJoinedToTrans.eItem.ID)
				{
					if(arrCurrentAmounts !=null)
					{
						lstDltAllocs.Add(
							new DTO.DltAlloc(
								Helper.GetFK(oCurrentItem.TransactionReference).Value, 
								Helper.GetFK(oCurrentTrans.PostReference), 
								oCurrentTrans.Descrip, 
								oCurrentTrans.Instant, 
								oCurrentItem.ID, 
								oCurrentItem.Descrip, 
								new u.ROArray<int>(arrCurrentAmounts))
							);
					}
					arrCurrentAmounts = new int[aParticipants.Count];
					oCurrentTrans = aDltAllocJoinedToItemJoinedToTrans.eTransaction;
					oCurrentItem =  aDltAllocJoinedToItemJoinedToTrans.eItem;
				}
				int i = aParticipants.IndexFromID(	Helper.GetFK(aDltAllocJoinedToItemJoinedToTrans.eDltAlloc.ParticipantReference).Value);
				if(arrCurrentAmounts[i]!=0)
					throw new s.Exception("ServiceEF.cs:1541");
				arrCurrentAmounts[i] =				aDltAllocJoinedToItemJoinedToTrans.eDltAlloc.Amount;
			}
			if(arrCurrentAmounts !=null)
			{
				lstDltAllocs.Add(
					new DTO.DltAlloc(
						Helper.GetFK(oCurrentItem.TransactionReference).Value, 
						Helper.GetFK(oCurrentTrans.PostReference), 
						oCurrentTrans.Descrip, 
						oCurrentTrans.Instant, 
						oCurrentItem.ID, 
						oCurrentItem.Descrip, 
						new u.ROArray<int>(arrCurrentAmounts))
					);
			}

			return lstDltAllocs.ToArray();
		}
		public DTO.DltAlloc[] GetDltAllocsOfTransactions(int iDltAllocAccntID, DTO.TransPred aTransPred)
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				du.Participants aParticipants = this.CreateDomainParticipants(this.GetParticipants(ctx));
				var query =
					from eDltAlloc in ctx.DltAlloc
					select new DltAllocJoinedToItemJoinedToTrans{eDltAlloc=eDltAlloc, eItem=eDltAlloc.Item, eTransaction=eDltAlloc.Item.Transaction};
				query = AppendWhereClauses(query, aTransPred);
				query = 
					from composit in query
					where composit.eItem.DltAllocAccnt.ID == iDltAllocAccntID
					orderby composit.eTransaction.Instant descending, composit.eTransaction.ID descending, composit.eItem.ID ascending
					select composit;
				return CreateDltAllocsArrayFromGrouping(query.ToList(), aParticipants);
			}
		}
		#endregion

		#region Post
		void Post(dal.LekEntities ctx)
		{
			dal.Post aPost = new dal.Post();
			aPost.Instant = s.DateTime.Now.Date;
			ctx.AddToPost(aPost);
			var qry = from eTransaction in ctx.Transaction where eTransaction.Post == null select eTransaction;
			foreach(dal.Transaction eTransaction in qry)
			{
				eTransaction.Post = aPost;
			}
			ctx.SaveChanges();
		}
		public void Post()
		{
			using (var ctx = new dal.LekEntities(CONN))
			{
				Post(ctx);
			}
		}
		#endregion

		#region Save Or Delete Transaction
		#region CodeWindow 068a
		gt.RowVersion GetTransactionTimestamp(int iTransactionID, dal.LekEntities ctx)
		{
			byte[] bytes = null;
			s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
			s.Data.Common.DbConnection conn = aEntityConnection.StoreConnection;
			s.Data.IDbCommand cmd = conn.CreateCommand();

			cmd.CommandText = "GetTransactionTimestamp";
			cmd.CommandType = System.Data.CommandType.StoredProcedure;
			
			cmd.Parameters.Add(new s.Data.SqlClient.SqlParameter("@ID", iTransactionID));
			
			s.Data.SqlClient.SqlParameter output = new System.Data.SqlClient.SqlParameter("@Timestamp", s.Data.SqlDbType.Timestamp);
			output.Direction = System.Data.ParameterDirection.Output;
			cmd.Parameters.Add(output);
			
			int iRC = cmd.ExecuteNonQuery();
			if(iRC!=-1)
				throw new s.Exception();
			
			bytes= (byte[])output.Value;
			return new gt.RowVersion(bytes);
		}
		void DeleteTransactionChildRecords(int iTransactionID, dal.LekEntities ctx)
		{
			s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
			s.Data.Common.DbConnection conn = aEntityConnection.StoreConnection;
			s.Data.IDbCommand cmd = conn.CreateCommand();

			cmd.CommandText = "DeleteTransactionChildRecords";
			cmd.CommandType = System.Data.CommandType.StoredProcedure;
			cmd.Parameters.Add(new s.Data.SqlClient.SqlParameter("@TransactionID", iTransactionID));
		
			cmd.ExecuteNonQuery();
		}
		#endregion
		#region CodeWindow 070
		dal.Transaction CreateTransactionReadyToAttach(int iTransactionID, gt.RowVersion aRowVersion)
		{
			dal.Transaction oDal = new DalEF.Transaction();
			oDal.ID = iTransactionID;
			oDal.EntityKey = Helper.CreateEntityKey(iTransactionID,typeof(dal.LekEntities).Name + "." + typeof(dal.Transaction).Name);
			oDal.timestamp = Helper.CreateORMRowVersion(aRowVersion);
			return oDal;
		}
		#endregion
		#region CodeWindow 073
		bool TransactionRowVersionMatches(int iTransactionID, dal.LekEntities ctx, gt.RowVersion aRowVersion)
		{
			gt.RowVersion oCurrentRowVersion = GetTransactionTimestamp(iTransactionID, ctx);
			return gt.RowVersion.ValueEquals(oCurrentRowVersion, aRowVersion);
		}
		#endregion
		#region CodeWindow 076
		void SetDALObjectFromDomainObject(du.ITransaction oDmn, dal.Transaction oDal, dal.LekEntities ctx)
		{
			oDal.Descrip = oDmn.Descrip;
			oDal.Instant = oDmn.Instant;
			Helper.EnsureFK(oDal.ParticipantReference, ctx, oDmn.ParticipantID);
			foreach (DTO.Item aItem in oDmn.Items)
			{
				dal.Item aDALItem = new dal.Item();
				aDALItem.Descrip = aItem.Descrip;
				Helper.EnsureFK(aDALItem.DltAllocAccntReference, ctx, aItem.DltAllocAccntID);

				for (int iParticipant = 0; iParticipant < oDmn.ParticipantCount; iParticipant++)
				{
					int iParticipantAmount = aItem.ParticipantAmounts[iParticipant];
					if (iParticipantAmount == 0)
						continue;
					dal.DltAlloc aDALDltAlloc = new dal.DltAlloc();
					aDALDltAlloc.Amount = iParticipantAmount;
					int iParticipantID = oDmn.GetParticipantID(iParticipant);
					Helper.EnsureFK(aDALDltAlloc.ParticipantReference, ctx, iParticipantID);
					
					aDALItem.DltAlloc.Add(aDALDltAlloc);
				}
				oDal.Item.Add(aDALItem);
			}
			foreach (DTO.NWAccntDlt aNWAccntDlt in oDmn.NWAccntDlts)
			{
				dal.NWAccntDlt aDALNWAccntDlt = new dal.NWAccntDlt();
				aDALNWAccntDlt.Amount = aNWAccntDlt.Amount;
				Helper.EnsureFK(aDALNWAccntDlt.NWAccntReference, ctx, aNWAccntDlt.NWAccntID);
				
				oDal.NWAccntDlt.Add(aDALNWAccntDlt);
			}
			for (int iParticipant = 0; iParticipant < oDmn.ParticipantCount; iParticipant++)
			{
				int iParticipantWashAmount = oDmn.GetWashAmount(iParticipant);
				if (iParticipantWashAmount == 0)
					continue;
				dal.WashDlt aDALWashDlt = new dal.WashDlt();
				aDALWashDlt.Amount = iParticipantWashAmount;
				int iParticipantID = oDmn.GetParticipantID(iParticipant);
				Helper.EnsureFK(aDALWashDlt.ParticipantReference, ctx, iParticipantID);
				
				oDal.WashDlt.Add(aDALWashDlt);
			}
		}
		#endregion
		#region CodeWindow 079
		dal.Transaction LLSaveTransaction(du.ITransaction oDmn, bool bAssumeInBalance, dal.LekEntities ctx)
		{
			if (!bAssumeInBalance)
			{
				if (0 != oDmn.GetAmountNWDltsExceedAllocDltsBy())
					throw new ArgumentException("transaction not in balance");
			}
			dal.Transaction oDAL=null;
			if (oDmn.ID.HasValue)
			{
				if(!TransactionRowVersionMatches(oDmn.ID.Value, ctx, oDmn.TheRowVersion))
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				DeleteTransactionChildRecords(oDmn.ID.Value, ctx);

			//SET FIELDS, THEN ATTACH
			//doesn't work: Call to Attach will cause framework to try to attach 
			//all the child items as modified entities, 
			//even though they are actually new entities
			//Since all the (new, unsaved) child entities have an ID of 0,
			//the framework will think that we are attempting to attach 
			//multiple items all with an ID of "0" (which it won't allow).
			//rather than adding the children as new entities.
			//	oDAL = CreateTransactionReadyToAttach(oDmn.ID.Value, oDmn.TheRowVersion);
			//	SetDALObjectFromDomainObject(oDmn, oDAL, ctx);
			//	ctx.Attach(oDAL);
			//	Helper.SetAllPropsAsModified(ctx, oDAL);

			//ATTACH, THEN SET FIELDS
			//doesn't work: when we finally get to save changes, it will use ParticipantID in a 
			//concurrency check, which will fail since at the moment the object was attached
			//the ParticipantID was set to null.  How do I disable the concurrency check on ParticipantID?
			//	oDAL = CreateTransactionReadyToAttach(oDmn.ID.Value, oDmn.TheRowVersion);
			//	ctx.Attach(oDAL);
			//	SetDALObjectFromDomainObject(oDmn, oDAL, ctx);
			//	Helper.SetAllPropsAsModified(ctx, oDAL);

			//GIVE UP, QUERY FOR IT TO ATTACH IT.
				oDAL = ctx.Transaction.Where(o=>o.ID == oDmn.ID.Value).ToList().FirstOrDefault();//The "ToList" part is required against SQLServer 2000, but not SQLSever 2005.
				SetDALObjectFromDomainObject(oDmn, oDAL, ctx);
			}
			else
			{
				oDAL = new dal.Transaction();
				SetDALObjectFromDomainObject(oDmn, oDAL, ctx);
				ctx.AddToTransaction(oDAL);
			}

			return oDAL;
		}
		#endregion
#if SQLSERVER2005
		#region CodeWindow 082
		public int SaveTransaction(DTO.Transaction aTransaction, bool bAssumeInBalance)
		{
			du.ITransaction oDmn = du.TransactionFactory.CreateDomainTransation(aTransaction);
			int iID;
			using (var ctx = new dal.LekEntities(CONN))
			using (s.Transactions.TransactionScope tran = new System.Transactions.TransactionScope())
			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();

					dal.Transaction oDal= LLSaveTransaction(oDmn, bAssumeInBalance, ctx);
					ctx.SaveChanges();
					iID = oDal.ID;
					tran.Complete();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
			return iID;
		}
		#endregion
#else
		public int SaveTransaction(DTO.Transaction aTransaction, bool bAssumeInBalance)
		{
			du.ITransaction oDmn = du.TransactionFactory.CreateDomainTransation(aTransaction);
			int iID;
			
			//If I attempt to use an ADO transaction I get the following error
			//on SaveChanges: "SqlConnection does not support parallel transactions."
			//	s.Data.Common.DbTransaction tran = null;

			using (var ctx = new dal.LekEntities(CONN))
			
			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();
		//			tran = conn.BeginTransaction(); 
		//			ctx.Transaction = tran; //read only prop
					dal.Transaction oDal= LLSaveTransaction(oDmn, bAssumeInBalance, ctx);
					ctx.SaveChanges();
					iID = oDal.ID;

		//			tran.Commit();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
		//			if(tran!=null)
		//				tran.Rollback();

					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
			return iID;
		}
#endif
		void DeleteTransactionWithNoChildren(int iTransactionID, gt.RowVersion aRowVersion, dal.LekEntities ctx)
		{
			//If I have already retrieved it to get the version then I won't be able to attach
			dal.Transaction oDal = CreateTransactionReadyToAttach(iTransactionID, aRowVersion);
			ctx.Attach(oDal);
			
			//If I have already retrieved it then it will just pull it from the cache.
			//	dal.Transaction eTransaction = ctx.TryGetByID<dal.Transaction>(iTransactionID);
			//	if(eTransaction == null)
			//		return;
		
			ctx.DeleteObject(oDal);
		}
#if SQLSERVER2005
		public void DeleteTransaction(int iTransactionID, gt.RowVersion oTransactionRowVersion)
		{
			using (var ctx = new dal.LekEntities(CONN))
			using (s.Transactions.TransactionScope tran = new System.Transactions.TransactionScope())
			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();

					//Not really needed if we use a transaction (exception will get thrown in the part of the delete that
					//deletes the parent record and the prior executed part that deleted the children will get rolled back)
					//and we must use a transaction or the record could change after we check the row version
					//but before we delete the transaction
					//It will save us from having to perform a rollback in 99.9% of the concurrency problems,
					//so if concurrency problems are very frequent it would be worth the cost to check.
					//I will leave it in just to exercise it.
					if(!TransactionRowVersionMatches(iTransactionID, ctx, oTransactionRowVersion))
						throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);

					DeleteTransactionChildRecords(iTransactionID, ctx);
					DeleteTransactionWithNoChildren(iTransactionID, oTransactionRowVersion, ctx);

					ctx.SaveChanges();
					tran.Complete();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
		}
#else
		public void DeleteTransaction(int iTransactionID, gt.RowVersion oTransactionRowVersion)
		{
			//If I attempt to use an ADO transaction I get the following error
			//on SaveChanges: "SqlConnection does not support parallel transactions."
			//s.Data.Common.DbTransaction tran = null;

			using (var ctx = new dal.LekEntities(CONN))

			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();
				//	tran = conn.BeginTransaction();
				//	ctx.Transaction = tran; //read only prop

					//Not really needed if we use a transaction (exception will get thrown in the part of the delete that
					//deletes the parent record and the prior executed part that deleted the children will get rolled back)
					//and we must use a transaction or the record could change after we check the row version
					//but before we delete the transaction
					//It will save us from having to perform a rollback in 99.9% of the concurrency problems,
					//so if concurrency problems are very frequent it would be worth the cost to check.
					//I will leave it in just to exercise it.
					if(!TransactionRowVersionMatches(iTransactionID, ctx, oTransactionRowVersion))
						throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);

					DeleteTransactionChildRecords(iTransactionID, ctx);
					DeleteTransactionWithNoChildren(iTransactionID, oTransactionRowVersion, ctx);

					ctx.SaveChanges();
			//		tran.Commit();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
			//		if(tran!=null)
			//			tran.Rollback();

					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
		}
#endif
		#endregion

		#region ResetItemsInTransactions
		class TransUpdateOfSelItems : Dictionary<int, DTO.ItemUpdate>
		{
			public int TransactionID { get; private set; }
			public TransUpdateOfSelItems(int iTransactionID)
			{
				TransactionID = iTransactionID;
			}
		}
		List<TransUpdateOfSelItems> CreateListOfDictsOfItemsByIDForTransactionsFromSortedCollectionOfItemUpdates(IEnumerable<DTO.ItemUpdate> strmItemUpdatesSorted)
		{
			List<TransUpdateOfSelItems> lstTransactionItemDicts = new List<TransUpdateOfSelItems>();
			TransUpdateOfSelItems dictItems = null;
			foreach (DTO.ItemUpdate aItemUpdate in strmItemUpdatesSorted)
			{
				if (dictItems != null && dictItems.TransactionID == aItemUpdate.TransactionID)
				{
					dictItems[aItemUpdate.ItemID] = aItemUpdate;
					continue;
				}
				if (dictItems != null)
					lstTransactionItemDicts.Add(dictItems);

				dictItems = new TransUpdateOfSelItems(aItemUpdate.TransactionID);
				dictItems[aItemUpdate.ItemID] = aItemUpdate;
			}
			if (dictItems != null)
				lstTransactionItemDicts.Add(dictItems);

			return lstTransactionItemDicts;
		}
		void UpdateItemsInTransaction(TransUpdateOfSelItems dictItemUpdates, int[] arrParticipantIDs, Dictionary<int, dal.DltAllocAccnt> dictOfDltAllocAccntsByID, dal.LekEntities ctx)
		{
			du.ITransaction aTransaction = LLGetTransaction(dictItemUpdates.TransactionID);
			IEnumerable<DTO.Item> strmCurrentItems = aTransaction.Items;

			du.TransactionItemUpdate aItemsUpdate = new du.TransactionItemUpdate(arrParticipantIDs);

			foreach (DTO.Item aCurrentItem in strmCurrentItems)
			{
				DTO.ItemUpdate aItemUpdate = null;
				dictItemUpdates.TryGetValue(aCurrentItem.ID, out aItemUpdate);
				if (aItemUpdate != null)
					aItemsUpdate.AddItem(aCurrentItem.ID, aCurrentItem.Descrip, aItemUpdate.DltAllocAccntID, dictOfDltAllocAccntsByID[aItemUpdate.DltAllocAccntID].Budgeted, aItemUpdate.ParticipantAmounts);
				else
					aItemsUpdate.AddItem(aCurrentItem.ID, aCurrentItem.Descrip, aCurrentItem.DltAllocAccntID, dictOfDltAllocAccntsByID[aCurrentItem.DltAllocAccntID].Budgeted, aCurrentItem.ParticipantAmounts);
			}
			aTransaction.ResetItems(aItemsUpdate);
			LLSaveTransaction(aTransaction, /*bAssumeInBalance=*/false, ctx);
		}
#if SQLSERVER2005
		public void ResetItemsInTransactions(DTO.ItemUpdate[] arrItemUpdates)
		{
			Dictionary<int, dal.DltAllocAccnt> dictOfDltAllocAccntsByID;
			using (var ctx = new dal.LekEntities(CONN))
			{
			
				dictOfDltAllocAccntsByID = GetDictionaryOfDltAllocAccnts(ctx);
			}
			du.Participants aParticipants = this.CreateDomainParticipants(this.GetParticipants());
			int[] arrParticpantIDs = aParticipants.GetArrayOfIDs();
		//	Dictionary<string, int> dictOfDltAllocAccntsByName = GetDictOfDltAllocAccntIDsByName();
			IEnumerable<DTO.ItemUpdate> strmItemUpdatesSorted = from DTO.ItemUpdate aItemUpdate in arrItemUpdates orderby aItemUpdate.TransactionID, aItemUpdate.ItemID select aItemUpdate;
			
			List<TransUpdateOfSelItems> lstDictsOfItemsForTransactions = CreateListOfDictsOfItemsByIDForTransactionsFromSortedCollectionOfItemUpdates(strmItemUpdatesSorted);
			using (var ctx = new dal.LekEntities(CONN))
			using (s.Transactions.TransactionScope tran = new System.Transactions.TransactionScope())
			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();

					foreach (TransUpdateOfSelItems dictItems in lstDictsOfItemsForTransactions)
					{
						UpdateItemsInTransaction(dictItems, arrParticpantIDs, dictOfDltAllocAccntsByID, ctx);
					}
					ctx.SaveChanges();
					tran.Complete();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
		}
#else
		public void ResetItemsInTransactions(DTO.ItemUpdate[] arrItemUpdates)
		{
			Dictionary<int, dal.DltAllocAccnt> dictOfDltAllocAccntsByID;
			using (var ctx = new dal.LekEntities(CONN))
			{
			
				dictOfDltAllocAccntsByID = GetDictionaryOfDltAllocAccnts(ctx);
			}
			du.Participants aParticipants = this.CreateDomainParticipants(this.GetParticipants());
			int[] arrParticpantIDs = aParticipants.GetArrayOfIDs();
		//	Dictionary<string, int> dictOfDltAllocAccntsByName = GetDictOfDltAllocAccntIDsByName();
			IEnumerable<DTO.ItemUpdate> strmItemUpdatesSorted = from DTO.ItemUpdate aItemUpdate in arrItemUpdates orderby aItemUpdate.TransactionID, aItemUpdate.ItemID select aItemUpdate;
			
			List<TransUpdateOfSelItems> lstDictsOfItemsForTransactions = CreateListOfDictsOfItemsByIDForTransactionsFromSortedCollectionOfItemUpdates(strmItemUpdatesSorted);

			//If I attempt to use an ADO transaction I get the following error
			//on SaveChanges: "SqlConnection does not support parallel transactions."
			//s.Data.Common.DbTransaction tran = null;

			using (var ctx = new dal.LekEntities(CONN))
			{
				s.Data.Common.DbConnection conn =null;
				try
				{
					s.Data.EntityClient.EntityConnection aEntityConnection = (s.Data.EntityClient.EntityConnection)ctx.Connection;
					conn = aEntityConnection.StoreConnection;
					conn.Open();
				//	tran = ctx.Connection.BeginTransaction();
				//	ctx.Transaction = tran; //read only prop
					foreach (TransUpdateOfSelItems dictItems in lstDictsOfItemsForTransactions)
					{
						UpdateItemsInTransaction(dictItems, arrParticpantIDs, dictOfDltAllocAccntsByID, ctx);
					}
					ctx.SaveChanges();
			//		tran.Commit();
				}
				catch(s.Data.OptimisticConcurrencyException)
				{
			//		if(tran!=null)
			//			tran.Rollback();

					//I think this will never happen because concurrency exception will
					//always occur in the call to "TransactionRowVersionMatches".
					//But since that is just a questionable optimization that we might remove
					//I will leave this
					throw su.ServerUtil.CreateConcurrencyFaultException(typeof(dal.Transaction).Name);
				}
				finally
				{
					if(conn!=null && conn.State == System.Data.ConnectionState.Open)
						conn.Close();
				}
			}
		}
#endif
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Austin Regional Clinic
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions