passing value from activity to another in WF - android-activity

I'm working with WF.
I made a custom activity called Draft_Doc:
public sealed class Draft_Doc : CodeActivity<string>
{
protected override string Execute(CodeActivityContext context)
{
C.Send_Task_Msg(unique_name, "Draft");
return "Draft";
}
}
I made another activity that contains a bookmark.
public sealed class WaitingTheApproval : NativeActivity
{
WorkflowInstanceProxy instance;
Service1Client C = new Service1Client();
public InArgument<string> previous_stage { get; set; }
public string stageName;
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddDefaultExtensionProvider<MyExtension>(() => new MyExtension());
//RuntimeArgument argSql = new RuntimeArgument("SqlConnectionString", typeof(String), ArgumentDirection.In);
}
protected override bool CanInduceIdle
{
get { return true; }
}
protected override void Execute(NativeActivityContext context)
{
var bookmark = context.CreateBookmark("MyBookmark", BookmarkResumed);
var extension = context.GetExtension<MyExtension>();
instance = extension._instance;
stageName = context.GetValue(this.previous_stage);
stageName = previous_stage.Get(context);
WaitSome(bookmark);
}
}
What I want is, when I drag and drop these two activities in rehosted workflow. I want to drag Draft_Doc first then I will link the WaitingTheApproval with it.
So, I want the return value from Draft_Doc set in the InArgument previous_stage in WaitingTheApproval at runtime.
Anyhelp?

There is no way to pass a value from one activity to another directly. you should assign the value to a Variable in the first activity and use the variable which has been assigned in the second activity.

Related

How to Create Lookup by Account Type using DimensionDynamicAccountController?

I have a problem.
I have in my new table two new fields
1) Name -> AccountNum, EDT--> DimensionDynamicAccount
2) Name -> AccountType, EDT--> LedgerJournalACType
class declaration
:
public class FormRun extends ObjectRun
{
DimensionDynamicAccountController dimAccountController;
}
init (for the form):
public void init()
{
super();
dimAccountController = DimensionDynamicAccountController::construct(
MyTable_ds,
fieldstr(MyTable, LedgerDimension),
fieldstr(MyTable, AccountType));
}
4. Override the following methods on the Segmented Entry control instance in the form design.
public void jumpRef()
{
dimAccountController.jumpRef();
}
public void loadAutoCompleteData(LoadAutoCompleteDataEventArgs _e)
{
super(_e);
dimAccountController.loadAutoCompleteData(_e);
}
public void segmentValueChanged(SegmentValueChangedEventArgs _e)
{
super(_e);
dimAccountController.segmentValueChanged(_e);
}
public void loadSegments()
{
super();
dimAccountController.parmControl(this);
dimAccountController.loadSegments();
}
public boolean validate()
{
boolean isValid;
isValid = super();
isValid = dimAccountController.validate() && isValid;
return isValid;
}
5. Override the following methods on the data source field that backs the Segmented Entry control.
public Common resolveReference(FormReferenceControl _formReferenceControl)
{
return dimAccountController.resolveReference();
}
Now my problem is Lookup only works for AccountType=="Ledger" not for customer, Vendor etc...
If I have a AccountType == Vendor or similant but different to Ledger I see this
I would want to have same the same thing that's in the LedgerJournalTrans Form
There is a solution,
thanks all,
enjoy
This might be too obvious, but I think you're missing the lookup() method.
See:
\Forms\LedgerJournalTransDaily\Designs\Design\[Tab:Tab]\[TabPage:OverViewTab]\[Grid:overviewGrid]\SegmentedEntry:LedgerJournalTrans_AccountNum\Methods\lookup
public void lookup()
{
if (!ledgerJournalEngine.accountNumLookup(ledgerJournalTrans_AccountNum,
ledgerJournalTrans,
ledgerJournalTrans.OffsetAccountType,
ledgerJournalTrans.parmOffsetAccount(),
ledgerJournalTrans_Asset))
{
super();
}
}

How to change database schema on runtime in EF7 or EF core

My database have different schema depending on user selections on runtime.
My code is below:
public partial class FashionContext : DbContext
{
private string _schema;
public FashionContext(string schema) : base()
{
_schema = schema;
}
public virtual DbSet<Style> Styles { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(#"Server=.\sqlexpress;Database=inforfashionplm;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Style>()
.ToTable("Style", schema: _schema);
}
}
Upon testing. I created a context instance with 'schema1'.
So far so good.
But when I create another context instance with different schema 'schema2', the resulting data in which the schema is still on 'schema1'.
Here is the implementation:
using (var db = new FashionContext("schema1"))
{
foreach (var style in db.Styles)
{
Console.WriteLine(style.Name);
}
}
Console.ReadLine();
Console.Clear();
using (var db = new FashionContext("schema2"))
{
foreach (var style in db.Styles)
{
Console.WriteLine(style.Name);
}
}
Console.ReadLine();
Later I noticed that the OnModelCreating is called only one time, so it is never called again when you create a new context instance of the same connection string.
Is it possible to have dynamic schema on runtime? Note: this is possible in EF6
One of possible way was mentioned above, but briefly, so I will try to explain with examples.
You ought to override default ModelCacheKeyFactory and ModelCacheKey.
ModelCachekeyFactory.cs
internal sealed class CustomModelCacheKeyFactory<TContext> : ModelCacheKeyFactory
where TContext : TenantDbContext<TContext>
{
public override object Create(DbContext context)
{
return new CustomModelCacheKey<TContext>(context);
}
public CustomModelCacheKeyFactory([NotNull] ModelCacheKeyFactoryDependencies dependencies) : base(dependencies)
{
}
}
ModelCacheKey.cs, please review Equals and GetHashCode overridden methods, they are not best one and should be improved.
internal sealed class ModelCacheKey<TContext> : ModelCacheKey where TContext : TenantDbContext<TContext>
{
private readonly string _schema;
public ModelCacheKey(DbContext context) : base(context)
{
_schema = (context as TContext)?.Schema;
}
protected override bool Equals(ModelCacheKey other)
{
return base.Equals(other) && (other as ModelCacheKey<TContext>)?._schema == _schema;
}
public override int GetHashCode()
{
var hashCode = base.GetHashCode();
if (_schema != null)
{
hashCode ^= _schema.GetHashCode();
}
return hashCode;
}
}
Register in DI.
builder.UseSqlServer(dbConfiguration.Connection)
.ReplaceService<IModelCacheKeyFactory, CustomModelCacheKeyFactory<CustomContext>>();
Context sample.
public sealed class CustomContext : TenantDbContext<CustomContext>
{
public CustomContext(DbContextOptions<CustomContext> options, string schema) : base(options, schema)
{
}
}
You can build the model externally and pass it into the DbContext using DbContextOptionsBuilder.UseModel()
Another (more advanced) alternative is to replace the IModelCacheKeyFactory to take schema into account.
I found a way to recreate the compiled model on each context creation.
public partial class MyModel : DbContext {
private static DbConnection _connection
{
get
{
//return a new db connection
}
}
private static DbCompiledModel _model
{
get
{
return CreateModel("schema name");
}
}
public MyModel()
: base(_connection, _model, false)
{
}
private static DbCompiledModel CreateModel(string schema)
{
var modelBuilder = new DbModelBuilder();
modelBuilder.HasDefaultSchema(schema);
modelBuilder.Entity<entity1>().ToTable(schema + ".entity1");
var builtModel = modelBuilder.Build(_connection);
return builtModel.Compile();
}
}

How can I make Cirqus stop automatically creating new instances?

I have an aggregate root with a few events and commands. One of those commands is a CreateCommand. That command should create a new aggregate root with a given ID. Every other event/command should just update an existing aggregate root and fail if the aggregate root with the given ID doesn't exist.
How can I make Cirqus work this way?
This is how I configure my CommandProcessor:
var commandProcessor = CommandProcessor
.With()
#if DEBUG
.Logging(l =>
{
if (_useConsoleForLogging)
{
l.UseConsole(Logger.Level.Debug);
}
else
{
l.UseDebug(Logger.Level.Debug);
}
})
#endif
.EventStore(e => e.UseSqlServer(_connectionString, _eventsTableName))
.EventDispatcher(e => e.UseViewManagerEventDispatcher(viewManagers))
.Create();
This is the CreateCommand:
public class CreateCommand : ExecutableCommand
{
public CreateCommand()
{
CreatedGuid = Guid.NewGuid();
}
public Guid CreatedGuid { get; }
public override void Execute(ICommandContext context)
{
var root = context.Create<MyAggregateRoot>(CreatedGuid.ToString());
}
}
Of course this CreateCommand contains more code that emits a few events to immediately update some properties of the created instance, but I've removed them as they're not vital to this question.
You can do that by using ExecutableCommand to implement your own update command - you could call it UpdateCommand.
It could look something like this:
public abstract class UpdateCommand<TAggregateRoot>
{
readonly string _aggregateRootId;
protected UpdateCommand(string aggregateRootId)
{
_aggregateRootId = aggregateRootId;
}
public override void Execute(ICommandContext context)
{
var instance = context.Load<TAggregateRoot>(_aggregateRootId);
Update(instance);
}
public abstract void Update(TAggregateRoot instance);
}
and then all commands derived off of UpdateCommand would experience exceptions if they tried to address non-existing instances.
Similarly, you could ensure creation with a CreateCommand base class that would use ICommandContext's Create<TAggregateRoot> method to ensure that an existing instance was not accidentally being addressed.

Autofac LifetimeScope with BeginLifetimeScope not working

I am trying to evaluate the scoping of Autofac and as I understand it, when an instance has been declared as InstancePerLifetimeScope, then within the using(container.BeginLifetimeScope()) block, we should get the same instance. But in another such block, we should get a different instance. But my code (in linqpad) gives me the same instance. Windsor's lifestylescope however works as I think it should.
Code:
static IContainer glkernel;
void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Controller>();
builder.RegisterType<A>().As<IInterface>().InstancePerLifetimeScope();
glkernel = builder.Build();
using (glkernel.BeginLifetimeScope()){
Controller c1 = glkernel.Resolve<Controller>();
c1.GetA();//should get instance 1
c1.GetA();//should get instance 1
}
using (glkernel.BeginLifetimeScope()){
Controller d = glkernel.Resolve<Controller>();
d.GetA();//should get instance 2
d.GetA();//should get instance 2
}
}
public interface IInterface
{
void DoWork(string s);
}
public class A : IInterface
{
public A()
{
ID = "AAA-"+Guid.NewGuid().ToString().Substring(1,4);
}
public string ID { get; set; }
public string Name { get; set; }
public void DoWork(string s)
{
Display(ID,"working...."+s);
}
}
public static void Display(string id, string mesg)
{
mesg.Dump(id);
}
public class Controller
{
public Controller()
{
("controller ins").Dump();
}
public void GetA()
{
//IInterface a = _kernel.Resolve<IInterface>();
foreach(IInterface a in glkernel.Resolve<IEnumerable<IInterface>>())
{
a.DoWork("from A");
}
}
}
The output is:
controller ins
AAA-04a0
working....from A
AAA-04a0
working....from A
controller ins
AAA-04a0
working....from A
AAA-04a0
working....from A
Perhaps my understanding of scoping is wrong. If so, can you please explain.
What do I have to do to get a different instance in the second block?
The problem is you're resolving things out of the container - the glkernel instead of out of the lifetime scope. A container is a lifetime scope - the root lifetime scope.
Resolve out of the lifetime scope instead. That may mean you need to change up your controller to pass in the list of components rather than using service location.
public class Controller
{
private IEnumerable<IInterface> _interfaces;
public Controller(IEnumerable<IInterface> interfaces)
{
this._interfaces = interfaces;
("controller ins").Dump();
}
public void GetA()
{
foreach(IInterface a in this._interfaces)
{
a.DoWork("from A");
}
}
}
Then it's easy enough to switch your resolution code.
using (var scope1 = glkernel.BeginLifetimeScope()){
Controller c1 = scope1.Resolve<Controller>();
c1.GetA();
c1.GetA();
}
using (var scope2 = glkernel.BeginLifetimeScope()){
Controller c2 = scope2.Resolve<Controller>();
c2.GetA();
c2.GetA();
}
The Autofac wiki has some good information on lifetime scopes you might want to check out.

DataAnnotations and FluentValidation not working in MVC 2 project

I have edited the original question since the same error is occurring the difference being the implementation, I have now added Ninject to the mix.
I have created a class for the validation rules
public class AlbumValidator : AbstractValidator<Album> {
public AlbumValidator() {
RuleFor(a => a.Title).NotEmpty();
}
}
I have created a ValidatorModule for Ninject
internal class FluentValidatorModule : NinjectModule {
public override void Load() {
AssemblyScanner.FindValidatorsInAssemblyContaining<AlbumValidator>()
.ForEach(result => Bind(result.InterfaceType).To(result.ValidatorType).InSingletonScope());
}
}
Here is my ValidatorFactory
public class NinjectValidatorFactory : ValidatorFactoryBase {
public override IValidator CreateInstance(Type validatorType) {
if (validatorType.GetGenericArguments()[0].Namespace.Contains("DynamicProxies")) {
validatorType = Type.GetType(string.Format("{0}.{1}[[{2}]], {3}",
validatorType.Namespace,
validatorType.Name,
validatorType.GetGenericArguments()[0].BaseType.AssemblyQualifiedName,
validatorType.Assembly.FullName));
}
return Container.Get(validatorType) as IValidator;
}
IKernel Container { get; set; }
public NinjectValidatorFactory(IKernel container) {
Container = container;
}
}
and the relevant parts from my Global
protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
var factory = new NinjectValidatorFactory(Container);
ModelValidatorProviders.Providers.Add(
new FluentValidationModelValidatorProvider(factory));
DataAnnotationsModelValidatorProvider
.AddImplicitRequiredAttributeForValueTypes = false;
}
protected override IKernel CreateKernel() {
return Container;
}
IKernel Container {
get { return new StandardKernel(new FluentValidatorModule()); }
}
I load the sample site click on the create new album link and then click the create button leaving the title empty I am then greeted with the error protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
var factory = new NinjectValidatorFactory(Container);
ModelValidatorProviders.Providers.Add(
new FluentValidationModelValidatorProvider(factory));
DataAnnotationsModelValidatorProvider
.AddImplicitRequiredAttributeForValueTypes = false;
}
protected override IKernel CreateKernel() {
return Container;
}
IKernel Container {
get { return new StandardKernel(
new Bootstrapper(),
new FluentValidatorModule()); }
}
I load up the create form and click create leaving the title empty low and behold an error
This property cannot be set to a null value.
The line it references is within the Entity Framework auto generated class, I traced the
Namespace.Contains("DynamicProxies")
and it was returning false, is this because I told EF to use a custom namespace SampleMusicStore.Web?
Or am I missing something else?
Cheers.
The problem is that Entity Framework is generating dynamic proxies on your classes, and then your system is trying to validate against the proxy classes instead of the classes you defined.
The way to resolve this is the same as this answer.