/// <summary> /// Prefer WithExpressionFrom to keep dependencies between modules clean!. /// </summary> public static FluentInclude <F> WithExpressionTo <F, T>(this FluentInclude <F> fi, DynamicQueryManager dqm, Expression <Func <F, Lite <T> > > lambdaToMethodOrProperty, Func <string> niceName) where F : Entity where T : Entity { dqm.RegisterExpression(lambdaToMethodOrProperty, niceName); return(fi); }
public static FluentInclude <T> WithTree <T>(this FluentInclude <T> include, Func <T, MoveTreeModel, T>?copy = null) where T : TreeEntity, new() { RegisterExpressions <T>(); RegisterOperations <T>(copy); include.WithUniqueIndex(n => new { n.ParentRoute, n.Name }); return(include); }
/// <summary> /// Prefer WithExpressionFrom to keep dependencies between modules clean!. Uses NiceName as niceName. /// </summary> public static FluentInclude <F> WithExpressionTo <F, T>(this FluentInclude <F> fi, DynamicQueryManager dqm, Expression <Func <F, T> > lambdaToMethodOrProperty) where F : Entity where T : Entity { dqm.RegisterExpression(lambdaToMethodOrProperty, () => typeof(T).NiceName()); return(fi); }
/// <summary> /// Prefer WithExpressionFrom to keep dependencies between modules clean!. /// </summary> public static FluentInclude <F> WithExpressionTo <F, T>(this FluentInclude <F> fi, Expression <Func <F, T?> > lambdaToMethodOrProperty, Func <string> niceName) where F : Entity where T : Entity { QueryLogic.Expressions.Register(lambdaToMethodOrProperty, niceName); return(fi); }
/// <summary> /// Prefer WithExpressionFrom to keep dependencies between modules clean!. Uses typeof(T) NiceName as niceName. /// </summary> public static FluentInclude <F> WithExpressionTo <F, T>(this FluentInclude <F> fi, Expression <Func <F, T?> > lambdaToMethodOrProperty) where F : Entity where T : Entity { QueryLogic.Expressions.Register(lambdaToMethodOrProperty, () => typeof(T).NiceName()); return(fi); }
public static FluentInclude <T> WithVirtualMListInitializeOnly <T, L>(this FluentInclude <T> fi, Func <T, MList <L> > getMList, Expression <Func <L, Lite <T> > > getBackReference, Action <L, T> onSave = null) where T : Entity where L : Entity { Action <L, Lite <T> > setter = null; var sb = fi.SchemaBuilder; sb.Schema.EntityEvents <T>().Saving += (T e) => { if (GraphExplorer.IsGraphModified(getMList(e))) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { var mlist = getMList(e); if (!GraphExplorer.IsGraphModified(mlist)) { return; } if (setter == null) { setter = CreateSetter(getBackReference); } mlist.ForEach(line => setter(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } mlist.SetCleanModified(false); }; return(fi); }
public static FluentInclude <T> WithDelete <T>(this FluentInclude <T> fi, DeleteSymbol <T> delete) where T : Entity { new Graph <T> .Delete(delete) { Delete = (e, _) => e.Delete() } .Register(); return(fi); }
public static FluentInclude <T> WithConstruct <T>(this FluentInclude <T> fi, ConstructSymbol <T> .Simple construct, Func <object[], T> constructFunction) where T : Entity { new Graph <T> .Construct(construct) { Construct = constructFunction } .Register(); return(fi); }
public static FluentInclude <T> WithConstruct <T>(this FluentInclude <T> fi, ConstructSymbol <T> .Simple construct) where T : Entity, new() { new Graph <T> .Construct(construct) { Construct = (_) => new T() } .Register(); return(fi); }
public static FluentInclude <T> WithQuery <T, Q>(this FluentInclude <T> fi, DynamicQueryManager dqm, Expression <Func <T, Q> > simpleQuerySelector, Action <AutoDynamicQueryCore <Q> > modifyQuery) where T : Entity { dqm.RegisterQuery <Q>(typeof(T), () => { var autoQuery = DynamicQueryCore.Auto(Database.Query <T>().Select(simpleQuerySelector)); modifyQuery(autoQuery); return(autoQuery); }); return(fi); }
public static FluentInclude <T> WithSave <T>(this FluentInclude <T> fi, ExecuteSymbol <T> saveOperation) where T : Entity { new Graph <T> .Execute(saveOperation) { AllowsNew = true, Lite = false, Execute = (e, _) => { } } .Register(); return(fi); }
public static FluentInclude <T> WithDeletePart <T, L>(this FluentInclude <T> fi, Expression <Func <T, Lite <L> > > relatedEntity) where T : Entity where L : Entity { fi.SchemaBuilder.Schema.EntityEvents <T>().PreUnsafeDelete += query => { var toDelete = query.Select(relatedEntity).ToList().NotNull().Distinct().ToList();; return(new Disposable(() => { Database.DeleteList(toDelete); })); }; return(fi); }
public static FluentInclude <T> WithSave <T>(this FluentInclude <T> fi, ExecuteSymbol <T> saveOperation) where T : Entity { new Graph <T> .Execute(saveOperation) { CanBeNew = true, CanBeModified = true, Execute = (e, _) => { } } .Register(); return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Expression <Func <T, MList <L> > > mListField, Expression <Func <L, Lite <T>?> > backReference, ExecuteSymbol <L> saveOperation, DeleteSymbol <L> deleteOperation) where T : Entity where L : Entity { return(fi.WithVirtualMList(mListField, backReference, onSave: saveOperation == null ? null : new Action <L, T>((line, e) => { line.Execute(saveOperation); }), onRemove: deleteOperation == null ? null : new Action <L, T>((line, e) => { line.Delete(deleteOperation); }))); }
public static FluentInclude <T> WithDeletePart <T, L>(this FluentInclude <T> fi, Expression <Func <T, L> > relatedEntity) where T : Entity where L : Entity { fi.SchemaBuilder.Schema.EntityEvents <T>().PreUnsafeDelete += query => { if (ShouldAvoidDeletePart(typeof(L))) { return(null); } var toDelete = query.Select(relatedEntity).Select(a => a.ToLite()).ToList().NotNull().Distinct().ToList(); return(new Disposable(() => { var groups = toDelete.GroupsOf(Connector.Current.Schema.Settings.MaxNumberOfParameters).ToList(); groups.ForEach(l => Database.DeleteList(l)); })); }; return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Func <T, MList <L> > getMList, Expression <Func <L, Lite <T> > > getBackReference, ExecuteSymbol <L> saveOperation, DeleteSymbol <L> deleteOperation) where T : Entity where L : Entity { return(fi.WithVirtualMList(getMList, getBackReference, onSave: saveOperation == null ? null : new Action <L, T>((line, e) => { if (line.IsGraphModified) { line.Execute(saveOperation); } }), onRemove: deleteOperation == null ? null : new Action <L, T>((line, e) => { line.Delete(deleteOperation); }))); }
public static FluentInclude <T> WithDeletePart <T, L>(this FluentInclude <T> fi, Expression <Func <T, L> > relatedEntity, Expression <Func <T, bool> >?filter = null, Func <T, bool>?handleOnSaving = null) where T : Entity where L : Entity { fi.SchemaBuilder.Schema.EntityEvents <T>().PreUnsafeDelete += query => { if (ShouldAvoidDeletePart(typeof(L))) { return(null); } var filteredQuery = filter == null ? query : query.Where(filter); var toDelete = filteredQuery.Select(relatedEntity).Select(a => a.ToLite()).ToList().NotNull().Distinct().ToList(); return(new Disposable(() => { var groups = toDelete.Chunk(Connector.Current.Schema.Settings.MaxNumberOfParameters).ToList(); groups.ForEach(l => Database.DeleteList(l)); })); }; if (handleOnSaving != null) { fi.SchemaBuilder.Schema.EntityEvents <T>().Saving += e => { if (!e.IsNew && handleOnSaving !(e)) { var lite = e.InDB().Select(relatedEntity).Select(a => a.ToLite()).SingleEx(); if (!lite.Is(relatedEntity.Evaluate(e))) { Transaction.PreRealCommit += dic => { lite.Delete(); }; } } } } ; return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Expression <Func <T, MList <L> > > mListField, Expression <Func <L, Lite <T>?> > backReference, Action <L, T>?onSave = null, Action <L, T>?onRemove = null, bool?lazyRetrieve = null, bool?lazyDelete = null) //To avoid StackOverflows where T : Entity where L : Entity { fi.SchemaBuilder.Include <L>(); var mListPropertRoute = PropertyRoute.Construct(mListField); var backReferenceRoute = PropertyRoute.Construct(backReference, avoidLastCasting: true); if (fi.SchemaBuilder.Settings.FieldAttribute <IgnoreAttribute>(mListPropertRoute) == null) { throw new InvalidOperationException($"The property {mListPropertRoute} should have an IgnoreAttribute to be used as Virtual MList"); } RegisteredVirtualMLists.GetOrCreate(typeof(T)).Add(mListPropertRoute, new VirtualMListInfo(mListPropertRoute, backReferenceRoute)); var defLazyRetrieve = lazyRetrieve ?? (typeof(L) == typeof(T)); var defLazyDelete = lazyDelete ?? (typeof(L) == typeof(T)); Func <T, MList <L> > getMList = GetAccessor(mListField); Action <L, Lite <T> >?setter = null; bool preserveOrder = fi.SchemaBuilder.Settings.FieldAttributes(mListPropertRoute) ! .OfType <PreserveOrderAttribute>() .Any(); if (preserveOrder && !typeof(ICanBeOrdered).IsAssignableFrom(typeof(L))) { throw new InvalidOperationException($"'{typeof(L).Name}' should implement '{nameof(ICanBeOrdered)}' because '{ReflectionTools.GetPropertyInfo(mListField).Name}' contains '[{nameof(PreserveOrderAttribute)}]'"); } var sb = fi.SchemaBuilder; if (defLazyRetrieve) { sb.Schema.EntityEvents <T>().Retrieved += (T e, PostRetrievingContext ctx) => { if (ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } var query = Database.Query <L>() .Where(line => backReference.Evaluate(line) == e.ToLite()); MList <L> newList = preserveOrder ? query.ToVirtualMListWithOrder() : query.ToVirtualMList(); mlist.AssignAndPostRetrieving(newList, ctx); }; } if (preserveOrder) { sb.Schema.EntityEvents <T>().RegisterBinding <MList <L> >(mListField, shouldSet: () => !defLazyRetrieve && !VirtualMList.ShouldAvoidMListType(typeof(L)), valueExpression: (e, rowId) => Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMListWithOrder(), valueFunction: (e, rowId, retriever) => Schema.Current.CacheController <L>() !.Enabled ? Schema.Current.CacheController <L>() !.RequestByBackReference <T>(retriever, backReference, e.ToLite()).ToVirtualMListWithOrder(): Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMListWithOrder() ); } else { sb.Schema.EntityEvents <T>().RegisterBinding(mListField, shouldSet: () => !defLazyRetrieve && !VirtualMList.ShouldAvoidMListType(typeof(L)), valueExpression: (e, rowId) => Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMList(), valueFunction: (e, rowId, retriever) => Schema.Current.CacheController <L>() !.Enabled ? Schema.Current.CacheController <L>() !.RequestByBackReference <T>(retriever, backReference, e.ToLite()).ToVirtualMList() : Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMList() ); } sb.Schema.EntityEvents <T>().PreSaving += (T e, PreSavingContext ctx) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } if (mlist.Count > 0) { var graph = Saver.PreSaving(() => GraphExplorer.FromRoot(mlist).RemoveAllNodes(ctx.Graph)); GraphExplorer.PropagateModifications(graph.Inverse()); var errors = GraphExplorer.FullIntegrityCheck(graph); if (errors != null) { #if DEBUG var withEntites = errors.WithEntities(graph); throw new IntegrityCheckException(withEntites); #else throw new IntegrityCheckException(errors); #endif } } if (mlist.IsGraphModified) { e.SetSelfModified(); } }; sb.Schema.EntityEvents <T>().Saving += (T e) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } if (preserveOrder) { mlist.ForEach((o, i) => ((ICanBeOrdered)o).Order = i); } if (GraphExplorer.IsGraphModified(mlist)) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist != null && !GraphExplorer.IsGraphModified(mlist)) { return; } if (!(args.WasNew || ShouldConsiderNew(typeof(T)))) { var oldElements = mlist.EmptyIfNull().Where(line => !line.IsNew); var query = Database.Query <L>() .Where(p => backReference.Evaluate(p) == e.ToLite()); if (onRemove == null) { query.Where(p => !oldElements.Contains(p)).UnsafeDelete(); } else { query.Where(p => !oldElements.Contains(p)).ToList().ForEach(line => onRemove !(line, e)); } } if (mlist != null) { if (mlist.Any()) { if (setter == null) { setter = CreateSetter(backReference); } mlist.ForEach(line => setter !(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave !(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } } mlist.SetCleanModified(false); } }; sb.Schema.EntityEvents <T>().PreUnsafeDelete += query => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return(null); } //You can do a VirtualMList to itself at the table level, but there should not be cycles inside the instances var toDelete = Database.Query <L>().Where(se => query.Any(e => backReference.Evaluate(se).Is(e))); if (defLazyDelete) { if (toDelete.Any()) { toDelete.UnsafeDelete(); } } else { toDelete.UnsafeDelete(); } return(null); }; return(fi); }
public static FluentInclude <T> WithQuery <T, Q>(this FluentInclude <T> fi, DynamicQueryManager dqm, Func <DynamicQueryCore <Q> > lazyGetQuery) where T : Entity { dqm.RegisterQuery <Q>(typeof(T), () => lazyGetQuery()); return(fi); }
public static FluentInclude <T> WithVirtualMListInitializeOnly <T, L>(this FluentInclude <T> fi, Expression <Func <T, MList <L> > > mListField, Expression <Func <L, Lite <T>?> > backReference, Action <L, T>?onSave = null) where T : Entity where L : Entity { fi.SchemaBuilder.Include <L>(); Func <T, MList <L> > getMList = GetAccessor(mListField); Action <L, Lite <T> >?setter = null; var sb = fi.SchemaBuilder; sb.Schema.EntityEvents <T>().RegisterBinding(mListField, shouldSet: () => false, valueExpression: (e, rowId) => Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMListWithOrder() ); sb.Schema.EntityEvents <T>().Saving += (T e) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } if (GraphExplorer.IsGraphModified(getMList(e))) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } if (!GraphExplorer.IsGraphModified(mlist)) { return; } if (setter == null) { setter = CreateSetter(backReference); } mlist.ForEach(line => setter !(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave !(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } mlist.SetCleanModified(false); }; return(fi); }
/// <summary> /// Uses NicePluralName as niceName /// </summary> public static FluentInclude <T> WithExpressionFrom <T, F>(this FluentInclude <T> fi, DynamicQueryManager dqm, Expression <Func <F, IQueryable <T> > > lambdaToMethodOrProperty) where T : Entity { dqm.RegisterExpression(lambdaToMethodOrProperty, () => typeof(T).NicePluralName()); return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Expression <Func <T, MList <L> > > mListField, Expression <Func <L, Lite <T> > > getBackReference, Action <L, T> onSave = null, Action <L, T> onRemove = null) where T : Entity where L : Entity { Func <T, MList <L> > getMList = mListField.Compile(); Action <L, Lite <T> > setter = null; bool preserveOrder = fi.SchemaBuilder.Settings.FieldAttributes(mListField) .OfType <PreserveOrderAttribute>() .Any(); var sb = fi.SchemaBuilder; sb.Schema.EntityEvents <T>().Retrieved += (T e) => { var mlist = getMList(e); List <L> list = Database.Query <L>() .Where(line => getBackReference.Evaluate(line) == e.ToLite()) .ToList(); if (preserveOrder) { list = list.OrderBy(le => ((ICanBeOrdered)le).Order).ToList(); } var rowIdElements = list .Select(line => new MList <L> .RowIdElement(line, line.Id, null)); ((IMListPrivate <L>)mlist).InnerList.AddRange(rowIdElements); }; sb.Schema.EntityEvents <T>().Saving += (T e) => { var mlist = getMList(e); if (preserveOrder) { mlist.ForEach((o, i) => ((ICanBeOrdered)o).Order = i); } if (GraphExplorer.IsGraphModified(mlist)) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { var mlist = getMList(e); if (!GraphExplorer.IsGraphModified(mlist)) { return; } if (!args.WasNew) { var oldElements = mlist.Where(line => !line.IsNew); var query = Database.Query <L>() .Where(p => getBackReference.Evaluate(p) == e.ToLite()); if (onRemove == null) { query.Where(p => !oldElements.Contains(p)).UnsafeDelete(); } else { query.ToList().ForEach(line => onRemove(line, e)); } } if (setter == null) { setter = CreateSetter(getBackReference); } mlist.ForEach(line => setter(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } mlist.SetCleanModified(false); }; sb.Schema.EntityEvents <T>().PreUnsafeDelete += query => query.SelectMany(e => Database.Query <L>().Where(se => getBackReference.Evaluate(se).RefersTo(e))).UnsafeDelete(); return(fi); }
public static FluentInclude <T> WithQuery <T, Q>(this FluentInclude <T> fi, DynamicQueryManager dqm, Expression <Func <T, Q> > simpleQuerySelector) where T : Entity { dqm.RegisterQuery <Q>(typeof(T), () => Database.Query <T>().Select(simpleQuerySelector)); return(fi); }
public static FluentInclude <T> WithQuery <T, Q>(this FluentInclude <T> fi, Func <DynamicQueryCore <Q> > lazyGetQuery) where T : Entity { QueryLogic.Queries.Register <Q>(typeof(T), () => lazyGetQuery()); return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Expression <Func <T, MList <L> > > mListField, Expression <Func <L, Lite <T> > > backReference, Action <L, T> onSave = null, Action <L, T> onRemove = null, bool?lazyRetrieveAndDelete = null) //To avoid StackOverflows where T : Entity where L : Entity { RegisteredVirtualMLists.GetOrCreate(typeof(T)).Add(typeof(L)); var lazy = lazyRetrieveAndDelete ?? (typeof(L) == typeof(T)); Func <T, MList <L> > getMList = GetAccessor(mListField); Action <L, Lite <T> > setter = null; bool preserveOrder = fi.SchemaBuilder.Settings.FieldAttributes(mListField) .OfType <PreserveOrderAttribute>() .Any(); if (preserveOrder && !typeof(ICanBeOrdered).IsAssignableFrom(typeof(L))) { throw new InvalidOperationException($"'{typeof(L).Name}' should implement '{nameof(ICanBeOrdered)}' because '{ReflectionTools.GetPropertyInfo(mListField).Name}' contains '[{nameof(PreserveOrderAttribute)}]'"); } var sb = fi.SchemaBuilder; if (lazy) { sb.Schema.EntityEvents <T>().Retrieved += (T e) => { if (ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } var query = Database.Query <L>() .Where(line => backReference.Evaluate(line) == e.ToLite()); MList <L> newList = preserveOrder ? query.ToVirtualMListWithOrder() : query.ToVirtualMList(); mlist.AssignAndPostRetrieving(newList); }; } if (preserveOrder) { sb.Schema.EntityEvents <T>().RegisterBinding <MList <L> >(mListField, shouldSet: () => !lazy && !VirtualMList.ShouldAvoidMListType(typeof(L)), valueExpression: e => Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMListWithOrder(), valueFunction: (e, retriever) => Schema.Current.CacheController <L>().RequestByBackReference <T>(retriever, backReference, e.ToLite()).ToVirtualMListWithOrder() ); } else { sb.Schema.EntityEvents <T>().RegisterBinding(mListField, shouldSet: () => !lazy && !VirtualMList.ShouldAvoidMListType(typeof(L)), valueExpression: e => Database.Query <L>().Where(line => backReference.Evaluate(line) == e.ToLite()).ExpandLite(line => backReference.Evaluate(line), ExpandLite.ToStringLazy).ToVirtualMList(), valueFunction: (e, retriever) => Schema.Current.CacheController <L>().RequestByBackReference <T>(retriever, backReference, e.ToLite()).ToVirtualMList() ); } sb.Schema.EntityEvents <T>().Saving += (T e) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist == null) { return; } if (preserveOrder) { mlist.ForEach((o, i) => ((ICanBeOrdered)o).Order = i); } if (GraphExplorer.IsGraphModified(mlist)) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return; } var mlist = getMList(e); if (mlist != null && !GraphExplorer.IsGraphModified(mlist)) { return; } if (!(args.WasNew || ShouldConsiderNew(typeof(T)))) { var oldElements = mlist.EmptyIfNull().Where(line => !line.IsNew); var query = Database.Query <L>() .Where(p => backReference.Evaluate(p) == e.ToLite()); if (onRemove == null) { query.Where(p => !oldElements.Contains(p)).UnsafeDelete(); } else { query.ToList().ForEach(line => onRemove(line, e)); } } if (mlist != null) { if (setter == null) { setter = CreateSetter(backReference); } mlist.ForEach(line => setter(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } mlist.SetCleanModified(false); } }; sb.Schema.EntityEvents <T>().PreUnsafeDelete += query => { if (VirtualMList.ShouldAvoidMListType(typeof(L))) { return(null); } //You can do a VirtualMList to itself at the table level, but there should not be cycles inside the instances var toDelete = Database.Query <L>().Where(se => query.Any(e => backReference.Evaluate(se).RefersTo(e))); if (lazy) { if (toDelete.Any()) { toDelete.UnsafeDelete(); } } else { toDelete.UnsafeDelete(); } return(null); }; return(fi); }
/// <summary> /// Uses typeof(T) NicePluralName as niceName /// </summary> public static FluentInclude <T> WithExpressionFrom <T, F>(this FluentInclude <T> fi, Expression <Func <F, IQueryable <T> > > lambdaToMethodOrProperty) where T : Entity { QueryLogic.Expressions.Register(lambdaToMethodOrProperty, () => typeof(T).NicePluralName()); return(fi); }
public static FluentInclude <T> WithExpressionFrom <T, F>(this FluentInclude <T> fi, Expression <Func <F, IQueryable <T> > > lambdaToMethodOrProperty, Func <string> niceName) where T : Entity { QueryLogic.Expressions.Register(lambdaToMethodOrProperty, niceName); return(fi); }
//public static FluentInclude<T> WithQuery<T, A>(this FluentInclude<T> fi, Func<Expression<Func<T, A>>> lazyQuerySelector) <-- C# Generic argument inference not so smart as to do this public static FluentInclude <T> WithQuery <T>(this FluentInclude <T> fi, Func <Expression <Func <T, object?> > > lazyQuerySelector) where T : Entity { QueryLogic.Queries.Register(typeof(T), new DynamicQueryBucket(typeof(T), () => DynamicQueryCore.FromSelectorUntyped(lazyQuerySelector()), Implementations.By(typeof(T)))); return(fi); }
public static FluentInclude <T> WithCache <T>(this FluentInclude <T> fi) where T : Entity { CacheLogic.TryCacheTable(fi.SchemaBuilder, typeof(T)); return(fi); }
public static FluentInclude <T> WithVirtualMList <T, L>(this FluentInclude <T> fi, Func <T, MList <L> > getMList, Expression <Func <L, Lite <T> > > getBackReference, Action <L, T> onSave = null, Action <L, T> onRemove = null) where T : Entity where L : Entity { Action <L, Lite <T> > setter = null; var sb = fi.SchemaBuilder; sb.Schema.EntityEvents <T>().Retrieved += (T e) => { var mlist = getMList(e); var rowIdElements = Database.Query <L>() .Where(line => getBackReference.Evaluate(line) == e.ToLite()) .ToList() .Select(line => new MList <L> .RowIdElement(line, line.Id, null)); ((IMListPrivate <L>)mlist).InnerList.AddRange(rowIdElements); }; sb.Schema.EntityEvents <T>().Saving += (T e) => { if (GraphExplorer.IsGraphModified(getMList(e))) { e.SetModified(); } }; sb.Schema.EntityEvents <T>().Saved += (T e, SavedEventArgs args) => { var mlist = getMList(e); if (!GraphExplorer.IsGraphModified(mlist)) { return; } if (!args.WasNew) { var oldElements = mlist.Where(line => !line.IsNew); var query = Database.Query <L>() .Where(p => getBackReference.Evaluate(p) == e.ToLite()); if (onRemove == null) { query.Where(p => !oldElements.Contains(p)).UnsafeDelete(); } else { query.ToList().ForEach(line => onRemove(line, e)); } } if (setter == null) { setter = CreateGetter(getBackReference); } mlist.ForEach(line => setter(line, e.ToLite())); if (onSave == null) { mlist.SaveList(); } else { mlist.ForEach(line => { if (GraphExplorer.IsGraphModified(line)) { onSave(line, e); } }); } var priv = (IMListPrivate)mlist; for (int i = 0; i < mlist.Count; i++) { if (priv.GetRowId(i) == null) { priv.SetRowId(i, mlist[i].Id); } } mlist.SetCleanModified(false); }; return(fi); }