I have a class named 'Employee'. Within the class is a method named getAgentsByHierarchy and it returns an array of all the agents with their corresponding ID and some other information.
Array{
[0] => Array{
[0] => code
[1] => id
[2] => name
[3] => role
}
}
I am extending this to two classes named 'Production' and 'Payroll'. These two classes have fetchAll() methods that calls Employee.getAgentsByHierarchy() and fetches all the agents and ONE extra data/field.
So when I call Production.fetchAll(), this is what it should return:
Array{
[0] => Array{
[0] => code
[1] => id
[2] => name
[3] => role
[4] => production_figures_in_digits
}
}
And when I call Payroll.fetchAll(), this is what it should return:
Array{
[0] => Array{
[0] => code
[1] => id
[2] => name
[3] => role
[4] => payroll_figures_in_digits
}
}
How do I go about this kind of design ?
My solution would be to include a parameter in the getAgentsByHierarchy() method that checks if the callee is from Production class or from Payroll class so that it would know what data to return. But then I think this way is not OOP way of doing things because if there's a new class that extends Salesforce, i would have to hardcode getAgentsByHierarchy() again to meet the requirements of the new class.
PS. I am new to design pattern, please forgive me with the way i wrote the title.
In ideal object oriented written application the parent class should never be concerned about the behavior of it's Child classes. Its the child class which is inheriting has to abide by the contracts of parent class.
So the Employee class should not be concerned about the existence of Production, Payroll or any other class inheriting from Employee class.
Ideally getAgentsByHierarchy should be overridden in Production and Payroll (or any other future child class) to embed the information specific to them in the array.
If Production has the information, to lower coupling, do it like this
Production.fetchAll() {
Employee.getAgentsByHierarchy();
Production.getFiguresInDigits();
// some method to combine them then return
}
And the same with Payroll
Related
I have a domain model like this:
In the mapping, I am using a table-per-hierarchy structure where all LineItemOption subtypes are stored in a single table and a named "OptionType" is used as a discriminator. This column isn't mapped to a property and isn't visible to the domain.
// FluentNHibernate ClassMap for LineItemOption
Map(lio => lio.Description);
DiscriminateSubClassesOnColumn("OptionType");
// FluentNHibernate SubclassMap for ColorOption
DiscriminatorValue("C")
// FluentNHibernate SubclassMap for GenericOption
DiscriminatorValue("O")
I am using the QueryOver API to fetch a list of Orders that contain a LineItem with a LineItemOption of a specific type containing a specific description.
private void AddColorRestrictionToQuery(
IQueryOver<Order, Order> query,
string color)
{
query.JoinQueryOver<LineItem>(order => order.LineItems)
.JoinQueryOver<LineItemOption>(line => line.Options)
.Where(opt => opt.Description.IsLike(color))
.Where(opt => opt is ColorOption); // See below
}
This results in NHibernate adding "WHERE OptionType = MyNamespace.Entities.ColorOption" to the query. Instead of using the discriminator value, it seems to be using the fully-qualified namespace+class name.
Why is NHibernate using the class name instead of its discriminator?
I believe you want:
query.JoinQueryOver<LineItem>(order => order.LineItems)
.JoinQueryOver<LineItemOption>(line => line.Options)
.Where(opt => opt.Description.IsLike(color))
.Where(opt => opt.GetType() == typeof(ColorOption));
I'm working on a web app using the Lithium Framework with a MongoDB database.
On one page of the application - I want to display data from multiple object types. I understand the concept of relationships (i.e. belongsTo, hasMany, etc.) between models. But, my questions has to do with Controller relationships.
For example, assume I have two objects named "People" and "Companies". I want to show specific information about Companies on a "people" view. I have done the following:
1) In the "People" model, I've added the following line:
public $belongsTo = array('Companies');
2) In the "PeopleController" file, I've also included a reference to the Companies Model, such as:
use app\models\Companies;
Now, within the PeopleController, I want to call a method in the CompaniesController file.
Do I access this by directly calling the CompaniesController file? Or, do I have to go thru the Company model.
In either case, I'll need help with the syntax. I'm having rouble figuring out the best way this should be called.
Thanks in advance for your help!
You should rethink your structure - you controller method should really grab all the resources you need for that view, it doesn't matter what they are.
So if you have a url '/people/bob' and you want to get the company data for Bob just add that to the view method of your People controller. Something like
People::first(array('conditions' => array('name' => 'Bob'), 'with' => 'Companies'));
You could instantiate a CompaniesController (maybe passing in $this->request to the 'request' option in the process) and then call the method in it. However, a better way to organize it is to move the common functionality from CompaniesController to Companies and call it from both places.
use app\models\Companies does not really make a "reference." It simply indicates that Companies really means app\models\Companies. I think an "alias" is a better way to think of it. See http://php.net/manual/en/language.namespaces.importing.php.
Example:
// in app/models/Companies.php
namespace app\models;
class Companies extends \lithium\data\Model {
public static function doSomething() {
// do something related to companies.
}
}
// in app/controllers/CompaniesController.php
namespace app\controllers;
use app\models\Companies;
class CompaniesController extends \lithium\action\Controller {
public function index() {
$result = Companies::doSomething();
return array('some' => 'data', 'for' => 'the view');
}
}
// in app/controllers/PeopleController.php
namespace app\controllers;
use app\models\Companies;
class PeopleController extends \lithium\action\Controller {
public function index() {
$result = Companies::doSomething();
return array('some' => 'data', 'for' => 'the view');
}
}
I use NHibernate for a dynamic website that its modules can be loaded dynamically, so when I want to build a sessionFactory, I use a way to find all assemblies and sort them with their dependencies
after all, I add them to Configuration instance I created and it works.
Now I want to change configuration type from hbm.xml files to fluent
I added below codes:
sessionFactory =
Fluently
.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008.ConnectionString(
c => c.FromAppSetting("connectionString")
)
)
.Mappings(
m => m.AutoMappings.Add(
AutoMap.Assemblies(
new FarayanConfig(),
assembliesArray
)
)
).BuildSessionFactory();
FarayanConfig is:
class FarayanConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Name.EndsWith("Entity");
}
public override bool IsVersion(FluentNHibernate.Member member)
{
return member.Name == "Version";
}
}
also I have a class in an assembly that will be loaded by this code (notice that assembly is not referenced, will be loaded dynamically) with a class named ControlEntity and also another class:
public class ControlEntityMap : ClassMap<ControlEntity>
{
public ControlEntityMap()
{
HasMany(x => x.Properties).Component(c => {
c.Map(v => v.Culture);
c.Map(v => v.Name);
c.Map(v => v.Value);
});
}
}
now the problem is constructor of ControlEntityMap will not execute!
what I must do?
Because of you are trying to use AutoMap.
You can use something like this:
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("your assembly name")))
Update:
You are doing right by ovverride DefaultAutomappingConfiguration for this situation but also you are trying to AutoMap all classes which ones end with "Entity" and your class which one you want to ignore it from AutoMap also ends with "Entity". I think you can seperate your classes in different namespaces and declare it in your ShouldMap property.
And there are some information in FluentNhibenate Wiki:
You can ignore base types by simply excluding them from your
ShouldMap(Type) method, that's sometimes the cleanest option; however,
if you want to be a bit more explicit you can use the IgnoreBase
method.
After AutoMap.AssemblyOf() we need to alter the conventions
that the auto mapper is using so it can identify our base-class.
AutoMap.AssemblyOf(cfg) .IgnoreBase();
We've added the IgnoreBase call which simply instructs the
automapper to ignore the Entity class; you can chain this call as many
times as needed.
I've configured Fluent NHibernate to map the entities in my project. None of my entities expose public properties (except their Id), all of their data is stored in private fields.
By using:
public override bool ShouldMap(Member member)
{
return member.Name == "Id" || (member.IsPrivate && member.IsField);
}
it successfully finds my fields, but then expects my database columns to be called things like _emailAddress.
How can I make it map _emailAddress to a column called EmailAddress? My SessionFactory initialisation looks like:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("AppConnection")))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<User>(new NHibMappingConfiguration())
.Conventions.Add(DefaultAccess.CamelCaseField(CamelCasePrefix.Underscore))))
.CurrentSessionContext("web")
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
using obviously a default access convention.
Thanks,
Matt
i think you have a couple of options here.
1. you could create your own Convention for naming columns (use the INamingConvention interface. see here).
2. you could create a MappingOverride class for individual classes and define the column name for each one:
mapping.Map(x => x.Name).Column("MyColumnName");
I have a class that has a password property that I want to store encrypted in the db. The property is a string type, and I have a custom type EncryptedStringType that I want NHibernate to use to map this to the database. Here is my relevant automapping code:
var mappings = AutoMap.AssemblyOf<Business>()
.Where(x=>x.IsSubclassOf(typeof(EntityBase)))
.IgnoreBase(typeof(EntityBase))
.Conventions.Add
(
ConventionBuilder.Id.Always(x =>
x.GeneratedBy.HiLo(HILO_TABLE, HILO_COLUMN, HILO_MAX_LO)),
ConventionBuilder.HasMany.Always(x => x.Cascade.AllDeleteOrphan()),
Table.Is(o => Inflector.Pluralize(o.EntityType.Name)),
PrimaryKey.Name.Is(o => "Id"),
ForeignKey.EndsWith("Id"),
DefaultLazy.Always(),
DefaultCascade.All()
);
I cannot figure out the syntax to override the type for the UserPassword property of the Business class though. I thought I should be able to do something with overrides like:
mappings.Override<Business>(map=> /* Not sure what to do here */);
Any help is appreciated.
Found the answer myself.
mappings.Override<Business>(map =>
{
map.Map(x => x.UserPassword).CustomType<EncryptedStringType>();
});
You could always create a mapping override class. Any conventions that can still be applied will be, but you can basically specify mappings similarly to a ClassMap that override the default conventions.
Using the call to mappings.Override(), it'd look something like:
mappings.Override<Business>(map=>map.Map(x=>x.UserPassword).CustomType(typeof(EncryptedStringType)));