What is the equivalant of the following Ninject statement in Structuremap - ninject.web.mvc

What is the equivalent of the following in Structuremap
kernel.Bind<IQueryDispatcher>().To<QueryDispatcher>();
kernel.Bind<ICommandDispatcher>().To<CommandDispatcher>();
kernel.Bind(x => x
.FromAssembliesMatching("MyApp.dll")
.SelectAllClasses().InheritedFrom(typeof(IQueryHandler<,>))
.BindAllInterfaces());
kernel.Bind(x => x
.FromAssembliesMatching("MyApp.dll")
.SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))
.BindAllInterfaces());
-Arun

This should do the job:
public class MyAppRegistry : Registry
{
public MyAppRegistry()
{
this.For<IQueryDispatcher>().Use<QueryDispatcher>();
this.For<ICommandDispatcher>().Use<CommandDispatcher>();
Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory(a => a.FullName.StartsWith("MyApp"));
scan.WithDefaultConventions();
scan.AddAllTypesOf(typeof(IQueryHandler<,>));
scan.AddAllTypesOf(typeof(ICommandHandler<>));
});
}
}

Related

Entity Framework Core 2.1. Proper way to update an object with a lot of sub objects

I'm developing an ASP.NET Core + EF Core application.
I'm struggling a bit (a lot actually) with the update method of the controller which manage the most complex object of my project.
The object looks something like this :
public class CIApplication : ConfigurationItem
{
public String InventoryCollectionQuery { get; set; }
public EnumCCMCIType CCMCIType { get; set; }
//Collection of DeploymentScenario
public virtual ICollection<DeploymentScenario> DeploymentScenarios { get; set; }
//Collection of SoftwareMeteringRules
public virtual ICollection<SoftwareMeteringRule> SoftwareMeteringRules { get; set; }
//Collection of AppLocalPresenceCondition
public virtual ICollection<AppLocalPresenceCondition> AppLocalPresenceConditions { get; set; }
}
And some of the objects in collections can also contains other collections and so, on and so on...
Actually my update methods works (which is below) but is a real pain to maintain when I do some evolutions on my model. As I developed it quite a while ago I'm wondering if there's a better approach to do this. And by better a mean a lot simpler for me :) sometimes I even wonder if it wouldn't be better to delete the object and recreate it.
var cIApplicationInDB = _context.CIApplications
.Include(c => c.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.InputVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.OutPutVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.InputVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.OutPutVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.DetectionMethods)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallationBehaviorRules)
.Include(c => c.SoftwareMeteringRules)
.Include(c => c.Catalogs)
.Include(c => c.Categories)
.Include(c => c.OwnerCompany)
.Include(c => c.AppLocalPresenceConditions)
.SingleOrDefault(c => c.ID == id);
_context.Entry(cIApplicationInDB).CurrentValues.SetValues(cIApplication);
// Updating Translations
foreach (var upTodateTranslation in cIApplication.Translations)
{
var existingTranslation = cIApplicationInDB.Translations.FirstOrDefault(t => t.Id == upTodateTranslation.Id);
if (existingTranslation == null)
{
cIApplicationInDB.Translations.Add(upTodateTranslation);
}
else
{
_context.Entry(existingTranslation).CurrentValues.SetValues(upTodateTranslation);
}
}
foreach (var ExistingTranslation in cIApplicationInDB.Translations)
{
if (!cIApplication.Translations.Any(t => t.Id == ExistingTranslation.Id))
{
_context.Remove(ExistingTranslation);
}
}
// Updating SoftwareMeteringRules
foreach (var upTodateSoftwareMeteringRule in cIApplication.SoftwareMeteringRules)
{
var existingSoftwareMeteringRule = cIApplicationInDB.SoftwareMeteringRules.FirstOrDefault(t => t.ID == upTodateSoftwareMeteringRule.ID);
if (existingSoftwareMeteringRule == null)
{
cIApplicationInDB.SoftwareMeteringRules.Add(upTodateSoftwareMeteringRule);
}
else
{
_context.Entry(existingSoftwareMeteringRule).CurrentValues.SetValues(upTodateSoftwareMeteringRule);
}
}
foreach (var existingSoftwareMeteringRule in cIApplicationInDB.SoftwareMeteringRules)
{
if (!cIApplication.SoftwareMeteringRules.Any(t => t.ID == existingSoftwareMeteringRule.ID))
{
_context.Remove(existingSoftwareMeteringRule);
}
}
// Updating DeploymentScenarios Graph
foreach (var upToDateDS in cIApplication.DeploymentScenarios)
{
// Look for incoming DS into the actual db CI
var existingDeploymentScenario = cIApplicationInDB.DeploymentScenarios.FirstOrDefault(d => d.ID == upToDateDS.ID);
// can't find DS in existing CI, it is new
if (existingDeploymentScenario == null)
{
// cIApplicationInDB.DeploymentScenarios.
cIApplicationInDB.DeploymentScenarios.Add(upToDateDS);
}
// Look if there are things to update in existing DS
else
{
_context.Entry(existingDeploymentScenario).CurrentValues.SetValues(upToDateDS);
// update DeploymentScenario translations
....
...doing the same way for all objects
// and then after going through all sub collections :
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException e)
{
if (!CIApplicationExists(id))
{
return NotFound();
}
else
{
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}

Phalcon 4 multi module backend not loading

I'm in windows using php-7.4.1 Architecture-x64, phalcon - 4.0.2, psr - 0.7.0 and follow instruction from 'https://docs.phalcon.io/4.0/en/application' but the problem is its always render frontend module & its view. I'm unable to find out what i'm doing wrong?
[Index.php]
use Phalcon\Mvc\Router;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
$di = new FactoryDefault();
$di->set('router',function () {
$router = new Router(false);
$router->setDefaultModule('frontend');
$router->add('/login',
[
'module' => 'backend',
'controller' => 'index',
'action' => 'index',
]
);
$router->add('/admin/products/:action',
[
'module' => 'backend',
'controller' => 'index',
'action' => 1,
]
);
return $router;
}
);
$application = new Application($di);
$application->registerModules(
[
'frontend' => [
'className' => \Multiple\Frontend\Module::class,
'path' => '../apps/frontend/Module.php',
],
'backend' => [
'className' => \Multiple\Backend\Module::class,
'path' => '../apps/backend/Module.php',
],
]
);
try {
$response = $application->handle($_SERVER["REQUEST_URI"]);
$response->send();
} catch (\Exception $e) {
echo $e->getMessage();
}
[Backend module]
<?php
namespace Multiple\Backend;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
public function registerAutoloaders(DiInterface $di = null)
{
$loader = new Loader();
$loader->registerNamespaces(
[
'Multiple\Backend\Controllers' => '../apps/backend/controllers/',
'Multiple\Backend\Models' => '../apps/backend/models/',
]
);
$loader->register();
}
public function registerServices(DiInterface $di)
{
$di->set('dispatcher',function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Multiple\Backend\Controllers');
return $dispatcher;
}
);
$di->set('view',function () {
$view = new View();
$view->setViewsDir('../apps/backend/views/');
return $view;
}
);
}
}
[Index Controller]
<?php
namespace Multiple\Backend\Controllers;
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function indexAction()
{
return '<h1>Back Controller!</h1>';
}
}
Did you set your namespaces in the frontend module as well? Like you did with registerAutoloaders in the backend.
Make sure you have registered your new module in
../app/bootstrap_web.php around line 47 which looks as shown below
$application->registerModules([
'frontend' => ['className' => 'MyApp\Modules\Frontend\Module'],
// <--- add your new module here --->
]);
and that your module class is also registered in the loader at ../app/config/loader.php around line 18 which looks as shown below
$loader->registerClasses([
'MyApp\Modules\Frontend\Module' => APP_PATH . '/modules/frontend/Module.php',
// <--- Add your new module class here --->
]);
Always keep an eye on your namespaces. I hope it helps.

Breeze: Differences between Entity Framework and NHibernate with many to many

Here is the situation:
WebApi v1
Breeze 1.4.7
EF 5.0/NHibernate 3.3.1
What We want: A many to many exposed as a many to one. A client can have multiple countries and a country can have multiple clients. A ClientCountry entity has been created for that purpose.
My mapping looks like this:
Entity Framework:
modelBuilder.Entity<Client>().HasKey(p => p.Id).Property(p=>p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Client>().Property(p => p.Abbreviation);
modelBuilder.Entity<Client>().Property(p => p.ClientSinceDate).IsRequired();
modelBuilder.Entity<Client>().Property(p => p.ClientUntilDate);
modelBuilder.Entity<Client>().Property(p => p.Name).IsRequired();
modelBuilder.Entity<Client>().Property(p => p.Website);
modelBuilder.Entity<Client>().HasMany(p => p.Contacts).WithRequired(p => p.Client).WillCascadeOnDelete(true);
modelBuilder.Entity<Client>().HasMany(p => p.ClientCountries).WithRequired(p => p.Client).WillCascadeOnDelete(true);
modelBuilder.Entity<Contact>().HasKey(p => p.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Contact>().Property(p => p.Username);
modelBuilder.Entity<Contact>().HasRequired(p => p.Client);
modelBuilder.Entity<Country>().HasKey(p => p.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Country>().Property(p => p.ValidFrom);
modelBuilder.Entity<Country>().Property(p => p.ValidTo);
modelBuilder.Entity<Country>().Property(p => p.Code);
modelBuilder.Entity<Country>().Property(p => p.DefaultLabel);
modelBuilder.Entity<Country>().Property(p => p.Description);
modelBuilder.Entity<Country>().Property(p => p.DisplayOrder);
modelBuilder.Entity<ClientCountry>().HasKey(p => p.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<ClientCountry>().Property(p => p.ValidFrom);
modelBuilder.Entity<ClientCountry>().Property(p => p.ValidTo);
modelBuilder.Entity<ClientCountry>().HasRequired(p => p.Client);
modelBuilder.Entity<ClientCountry>().HasRequired(p => p.Country);
NHibernate:
public class BaseMapping<T> : ClassMapping<T> where T : BaseEntity
{
public BaseMapping()
{
this.Lazy(true);
Id(x => x.Id, map => { map.Generator(Generators.GuidComb); });
}
}
public class ClientMap : BaseMapping<Client>
{
public ClientMap()
{
this.Property(x => x.Name);
this.Property(x => x.Abbreviation);
this.Property(x => x.ClientSinceDate, map => map.NotNullable(true));
this.Property(x => x.ClientUntilDate);
this.Property(x => x.City);
this.Property(x => x.Website);
this.Bag<Department>(x => x.Departments, colmap =>
{
colmap.Key(x => x.Column("ClientId"));
colmap.Inverse(true);
colmap.Cascade(Cascade.All | Cascade.DeleteOrphans);
}, map =>
{
map.OneToMany();
});
this.Bag<ClientCountry>(x => x.ClientCountries, colmap =>
{
colmap.Cascade(Cascade.All | Cascade.DeleteOrphans);
colmap.Key(p => p.Column("ClientId"));
colmap.Inverse(true);
}, map =>
{
map.OneToMany();
});
this.Bag<Contact>(x => x.Contacts, colmap =>
{
colmap.Key(x => x.Column("ClientId"));
colmap.Cascade(Cascade.All | Cascade.DeleteOrphans);
}, map =>
{
map.OneToMany();
});
}
}
public class CountryMap : BusinessRefEntityMapping<Country>
{
public CountryMap()
{
Bag<ClientCountry>(x => x.ClientCountries, colmap =>
{
colmap.Cascade(Cascade.All);
colmap.Key(p => p.Column("CountryId"));
}, map =>
{
map.OneToMany();
});
}
}
public class ClientCountryMap : BaseMapping<ClientCountry>
{
public ClientCountryMap()
{
Property(x => x.ValidFrom);
Property(x => x.ValidTo);
Property(x => x.ClientId, map =>
{
map.Column("ClientId");
map.Insert(false);
map.Update(false);
map.NotNullable(true);
});
Property(x => x.CountryId, map =>
{
map.Column("CountryId");
map.Insert(false);
map.Update(false);
map.NotNullable(true);
});
ManyToOne<Client>(x => x.Client, map =>
{
map.Column("ClientId");
map.Cascade(Cascade.All);
map.Insert(true);
map.Update(true);
map.NotNullable(true);
});
ManyToOne<Country>(x => x.Country, map =>
{
map.Column("CountryId");
map.Cascade(Cascade.All);
map.Insert(true);
map.Update(true);
map.NotNullable(true);
});
}
}
The js code:
$scope.create = function (index) {
var c = $scope.clients[index];
var newClientCountry = breezeService.manager.createEntity('ClientCountry', {
ValidFrom: Date(2013, 01, 01),
ValidTo: Date(2015, 01, 01),
Client: c,
Country: country,
});
breezeService.manager.saveChanges()
.then(function (data) {
$log.info('client created');
})
.fail(function (dat) {
$log.error('save client failed:' + data)
})
}
The issue: With NHibernate, saving a clientcountry results in this error message :"not-null property references a null or transient value CdT.EAI.DAL.ClientCountry.Country". With EF, all works as expected.
Is there something wrong with my code?
So, since there is no feedback yet, here's what we did to make it (more or less) work:
First, to be able to save a new ClientCountry(many to many with exposed junction table), we must do this:
public class ClientCountryMap : BaseMapping<ClientCountry>
{
public ClientCountryMap()
{
Property(x => x.ValidFrom);
Property(x => x.ValidTo);
Property(x => x.ClientId, map =>
{
map.Column("ClientId");
map.Insert(true);
map.Update(true);
map.NotNullable(true);
});
Property(x => x.CountryId, map =>
{
map.Column("CountryId");
map.Insert(true);
map.Update(true);
map.NotNullable(true);
});
ManyToOne<Client>(x => x.Client, map =>
{
map.Column("ClientId");
map.Cascade(Cascade.All);
map.Insert(false);
map.Update(false);
map.NotNullable(true);
});
ManyToOne<Country>(x => x.Country, map =>
{
map.Column("CountryId");
map.Cascade(Cascade.All);
map.Insert(false);
map.Update(false);
map.NotNullable(true);
});
}
}
The difference here is that the insert/update are inverted. Insert(true) and Update(true) must be set on the foreign key mapping and not the association. It differs from the breeze doc on that point.
The second is that Inverse(true) must be set on each collection association or all your collections will be deleted when updating the parent entity.
With that,changes, it seems to work as expected.
ps: It is fixed in the latest version (>1.4.8). The comments above don't apply anymore.

NHibernate and JoinAlias throw exception

I have query in HQL which works good:
var x =_session.CreateQuery("SELECT r FROM NHFolder f JOIN f.DocumentComputedRights r WHERE f.Id = " + rightsHolder.Id + " AND r.OrganisationalUnit.Id=" + person.Id);
var right = x.UniqueResult<NHDocumentComputedRight>();
Basically I receive NHDocumentComputedRight instance.
I've tried to implement the same query in QueryOver. I did this:
var right = _session.QueryOver<NHFolder>().JoinAlias(b => b.DocumentComputedRights, () => cp).Where(h => h.Id == rightsHolder.Id && cp.OrganisationalUnit.Id == person.Id)
.Select(u => cp).List<NHDocumentComputedRight>();
But I get null reference exception.
How can I implement this query in QueryOver?
Update (added mappings) - NHibernate 3.2:
public class FolderMapping: ClassMapping<NHFolder>
{
public FolderMapping()
{
Table("Folders");
Id(x => x.Id, map =>
{
map.Generator(IdGeneratorSelector.CreateGenerator());
});
//more not important properties...
Set(x => x.DocumentComputedRights, v =>
{
v.Table("DocumentComputedRightsFolder");
v.Cascade(Cascade.All | Cascade.DeleteOrphans);
v.Fetch(CollectionFetchMode.Subselect);
v.Lazy(CollectionLazy.Lazy);
}, h => h.ManyToMany());
Version(x => x.Version, map => map.Generated(VersionGeneration.Never));
}
}
public class DocumentComputedRightMapping : ClassMapping<NHDocumentComputedRight>
{
public DocumentComputedRightMapping()
{
Table("DocumentComputedRights");
Id(x => x.Id, map =>
{
map.Generator(IdGeneratorSelector.CreateGenerator());
});
//more not important properties...
ManyToOne(x => x.OrganisationalUnit, map =>
{
map.Column("OrganisationalUnit");
map.NotNullable(false);
map.Cascade(Cascade.None);
});
}
}
public class OrganisationUnitMapping : ClassMapping<NHOrganisationalUnit>
{
public OrganisationUnitMapping()
{
Table("OrganisationalUnits");
Id(x => x.Id, map =>
{
map.Generator(IdGeneratorSelector.CreateGenerator());
});
//more not important properties...
}
}
Thanks
AFAIK criteria/queryOver can only return the entity it was created for (NHFolder in your example) or columns which are set to entity with aliastobean. you could do a correlated subquery instead.
var subquery = QueryOver.Of<NHFolder>()
.JoinAlias(b => b.DocumentComputedRights, () => cp)
.Where(h => h.Id == rightsHolder.Id && cp.OrganisationalUnit.Id == person.Id)
.Select(u => cp.Id);
var right = _session.QueryOver<NHDocumentComputedRight>()
.WithSubquery.Where(r => r.Id).Eq(subquery)
.SingleOrDefault<NHDocumentComputedRight>();
I think you have a problem with the select statement, have you tried something like this:
var right = _session.QueryOver<NHFolder>()
.JoinAlias(b => b.DocumentComputedRights, () => cp)
.Select(x => x.DocumentComputedRights)
.Where(h => h.Id == rightsHolder.Id && cp.OrganisationalUnit.Id == person.Id)
.List<NHDocumentComputedRight>();
This is what is working for me so it should work in you case as well.
I would guess that the main reason behind the problem is the lack of proper overload on the Select method. In reality you would like to write it like this:
.JoinAlias(b => b.DocumentComputedRights, () => cp)
.Select(() => cp)
but the Expression<Func<object>> is not there. Hopefully it's going to be included in the next version.

Fluent Nhibernate Component Prefix

Is there a way to set the column prefix for a component in fluent. For example:
public class SomeClassMap : ClassMap < SomeClass >
{
public SomeClassMap()
{
CreateMap();
}
private void CreateMap()
{
WithTable("Class");
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Name).WithLengthOf(100);
Component<SomeComponent>(x => x.somecomponent, m =>
{
m.Map(x => x.Name).SetAttribute("column", "SomeComponentName");
m.Map(x => x.Summary).SetAttribute("column", "SomeComponentSummary");
.... etc ...
}
);
Is there a way to set "SomeComponent" prefixes instead of having to define them in a SetAttribute?
There's nothing implicit. AutoMapping does it, but not regular mapping. I've created an issue so you can track the status of this.
There is some good information here: http://nhforge.org/blogs/nhibernate/archive/2008/09/06/a-fluent-interface-to-nhibernate-part-2-value-objects.aspx that seems to be what you are wanting to do.
In particular the Action method demonstrated in this sample:
public class EmployeeMap : ClassMap<Employee>
{
private Action<ComponentPart<Address>> MapAddress(string columnPrefix)
{
return a =>
{
a.Map(x => x.AddressLine1, columnPrefix + "AddressLine1");
a.Map(x => x.AddressLine2, columnPrefix + "AddressLine2");
a.Map(x => x.PostalCode, columnPrefix + "PostalCode");
a.Map(x => x.City, columnPrefix + "City");
a.Map(x => x.Country, columnPrefix + "Country");
};
}
public EmployeeMap()
{
Id(x => x.Id);
Map(x => x.FirstName).CanNotBeNull().WithLengthOf(20);
Map(x => x.LastName).CanNotBeNull().WithLengthOf(20);
Component<Address>(x => x.HomeAddress, MapAddress("Home_"));
Component<Address>(x => x.WorkAddress, MapAddress("Work_"));
}
}