I want to make that all my Entities created form an existing database inherits from the same interface.
I suppose this can be done through the templates. And I've seen that ugly .tt file, but there is no help (or I haven't found it).
There are any documentation, examples, ... of the templates?
There are any tips or pre-made templates for common paradigms, for example N-Layer Design or Domain Driven Desing?
Look for "T4 Templates". That will give you introduction to T4 Templates (.tt files).
With a bit of searching you can easily extend this template to your needings. I did this myself already, but with a template from EF4. I don't know if the templates differ.
I made a little helper functions for this:
string Interfaces(EntityType entity)
{
string interfaces = string.Empty;
if (entity.Members.OfType<EdmProperty>().Any(edmProperty => edmProperty.Name == "Guid" && ((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.Guid))
{
interfaces += ", IHasWritableGuid";
}
return interfaces;
}
The part where the template writes the actually entity class (this differs for sure in the new template) is somewhat below "Write EntityType classes." in the EF4 template.
<#=Accessibility.ForType(entity)#>
<#=code.SpaceAfter(code.AbstractOption(entity))#>
partial class
<#=code.Escape(entity)#> :
<#=BaseTypeName(entity, code)#>
<#= Interfaces(entity) #>
Here I just added a call to my interfaces method.
I know this is not the exact answer, but it should give you help with editing the template file yourself. Just bite yourself through it. :)
Related
I use Enterprise Architect for code generation and I would like to automatically retrieve all tags (in my case Java annotations) of the interfaces that a class realizes. Consider the following example:
From this model, I want to generate a class that looks like this:
#AnnotationOfMyInterface
public class MyClass {
...
}
So I want to add annotations as tags to MyInterface that should be applied to MyClass during code generation. In the UI, tags of implemented interfaces are shown so I was hoping there is a way to get these tags during code generation.
I tried to edit the code generation templates and found macros to get
All interfaces that a class implements: %list="ClassInterface" #separator=", "%
All tags with a given name (of the class that code is being generated for): %classTag:"annotations"%
But unfortunately, I cannot combine these macros, i.e., I cannot pass one interface to the classTag macro so that I can retrieve the tags of that particular interface (and not the one I'm generating code for). Is there a way to get classTags of a specific class / interface?
I also tried to create a separate code generation template and "call" it from the main class code generation template. But inside my template, the classTag macro still only gets the tags of the class.
Thanks to the comments above and especially because of an answer to my question in EA's forum, I was able to setup a little proof of concept achieving what I wanted. I'm answering my question to document my solution in case someone has a similar problem in the future.
After Eve's hint in EA's forum I looked into creating an AddIn for Enterprise Architect to use this AddIn from a code generation template. I started by writing a basic AddIn as explained by #Geert Bellekens in this tutorial. Afterwards I changed the AddIn to fit my needs. This is how I finally got the tagged values (annotations) of the interfaces a class realizes:
First step:
Inside a code generation template, I get all the interfaces a class realizes and pass them to my AddIn:
$interfaces=%list="ClassInterface" #separator=", "%
%EXEC_ADD_IN("MyAddin","getInterfaceTags", $interfaces)%
Second step:
As documented here the repository objects gets passed along with the EXEC_ADD_IN call. I use the repository object and query for all interfaces using the names contained in $interfaces. I can then get the tagged values of each interface element. Simple prototype that achieves this for a single interface:
public Object getInterfaceTags(EA.Repository repo, Object args)
{
String[] interfaceNames = args as String[];
String firstInterfaceName = interfaceNames[0];
EA.Element interfaceElement = repo.GetElementsByQuery("Simple", firstInterfaceName).GetAt(0);
String tag = interfaceElement.TaggedValues.GetAt(0);
return interfaceElement.Name + " has tag value" + tag.Value;
}
I know, there are a couple of shortcomings but this is just a simple proof of concept for an idea that will most likely never be production code.
I'm looking for suggestions on how to approach using an ORM (in this case, EF5) in the design of modular Non-Monolithic applications, with a Core part and 3rd party Modules, where the Core has no direct Reference to the 3rd party Modules, and Modules only have a reference to Core/Common tables and classes.
For arguments sake, a close enough analogy would be DNN.
CodeFirst:
With CodeFirst, the approach I used was to build up the model of the Db was via reflection: in the Core's DbContext's DbInitialation phase, I used Reflection to find any class in any dll (eg Core or various Modules) decorated with IDbInitializer (a custom contract containing an Execute() method) to define just the dll's structure. Each dll added to the DbModel what it knew about itself.
Any subsequent Seeding was also handled in the same wa (searching for a specific IDbSeeder contract, and executing it).
Pro:
* the approach works for now.
* The same core DbContext can be used across all respositories, as long as each repo uses dbContext.GetSet(), rather than expecting it to be a property of the dbContext. No biggie.
Cons:
* it only works at startup (ie, adding new modules would require an AppPool refresh).
* CodeFirst is great for a POC. But in EF5, it's not mature enough for Enterprise work yet (and I can't wait for EF6 for StoredProcs and other features to be added).
* My DBA hates CodeFirst, at least for the Core, wanting to optimize that part with Stored Procs as much as as possible...We're a team, so I have to try to find a way to please him, if I can find a way...
Database-first:
The DbModel phase appears to be happening prior to the DbContext's constructor (reading from embedded *.edmx resource file). DbInitialization is never invoked (as model is deemed complete), so I can't add more tables than what the Core knows about.
If I can't add elements to the Model, dynamically, as one can with CodeFirst, it means that
* either the Core DbContext's Model has to have knowledge of every table in the Db -- Core AND every 3rd party module. Making the application Monolithic and highly coupled, defeating the very thing I am trying to achieve.
* Or each 3rd party has to create their own DbContext, importing Core tables, leading to
* versioning issues (module not updating their *.edmx's when Core's *.edmx is updated, etc.)
* duplication everywhere, in different memory contexts = hard to track down concurrency issues.
At this point, it seems to me that the CodeFirst approach is the only way that Modular software can be achieved with EF. But hopefully someone else know's how to make DatabaseFirst shine -- is there any way of 'appending' DbSet's to the model created from the embedded *.edmx file?
Or any other ideas?
I would consider using a sort of plugin architecture, since that's your overall design for the application itself.
You can accomplish the basics of this by doing something like the following (note that this example uses StructureMap - here is a link to the StructureMap Documentation):
Create an interface from which your DbContext objects can derive.
public interface IPluginContext {
IDictionary<String, DbSet> DataSets { get; }
}
In your Dependency Injection set-up (using StructureMap) - do something like the following:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IPluginContext>();
s.WithDefaultConventions();
});
For<IEnumerable<IPluginContext>>().Use(x =>
x.GetAllInstances<IPluginContext>()
);
For each of your plugins, either alter the {plugin}.Context.tt file - or add a partial class file which causes the DbContext being generated to derive from IPluginContext.
public partial class FooContext : IPluginContext { }
Alter the {plugin}.Context.tt file for each plugin to expose something like:
public IDictionary<String, DbSet> DataSets {
get {
// Here is where you would have the .tt file output a reference
// to each property, keyed on its property name as the Key -
// in the form of an IDictionary.
}
}
You can now do something like the following:
// This could be inside a service class, your main Data Context, or wherever
// else it becomes convenient to call.
public DbSet DataSet(String name) {
var plugins = ObjectFactory.GetInstance<IEnumerable<IPluginContext>>();
var dataSet = plugins.FirstOrDefault(p =>
p.DataSets.Any(ds => ds.Key.Equals(name))
);
return dataSet;
}
Forgive me if the syntax isn't perfect - I'm doing this within the post, not within the compiler.
The end result gives you the flexibility to do something like:
// Inside an MVC controller...
public JsonResult GetPluginByTypeName(String typeName) {
var dataSet = container.DataSet(typeName);
if (dataSet != null) {
return Json(dataSet.Select());
} else {
return Json("Unable to locate that object type.");
}
}
Clearly, in the long-run - you would want the control to be inverted, where the plugin is the one actually tying into the architecture, rather than the server expecting a type. You can accomplish the same kind of thing using this sort of lazy-loading, however - where the main application exposes an endpoint that all of the Plugins tie to.
That would be something like:
public interface IPlugin : IDisposable {
void EnsureDatabase();
void Initialize();
}
You now can expose this interface to any application developers who are going to create plugins for your architecture (DNN style) - and your StructureMap configuration works something like:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory(); // Upload all plugin DLLs here
// NOTE: Remember that this gives people access to your system!!!
// Given what you are developing, though, I am assuming you
// already get that.
s.AddAllTypesOf<IPlugin>();
s.WithDefaultConventions();
});
For<IEnumerable<IPlugin>>().Use(x => x.GetAllInstances<IPlugin>());
Now, when you initialize your application, you can do something like:
// Global.asax
public static IEnumerable<IPlugin> plugins =
ObjectFactory.GetInstance<IEnumerable<IPlugin>>();
public void Application_Start() {
foreach(IPlugin plugin in plugins) {
plugin.EnsureDatabase();
plugin.Initialize();
}
}
Each of your IPlugin objects can now contain its own database context, manage the process of installing (if necessary) its own database instance / tables, and dispose of itself gracefully.
Clearly this isn't a complete solution - but I hope it starts you off in a useful direction. :) If I can help clarify anything herein, please let me know.
While it's a CodeFirst approach, and not the cleanest solution, what about forcing initialization to run even after start up, as in the answer posted here: Forcing code-first to always initialize a non-existent database? (I know precisely nothing about CodeFirst, but seeing as this is a month old with no posts it's worth a shot)
My issue is simple: the code I'm writing is in English, but the interface is in Portuguese. Not a problem, as I can do this:
[Display (Name = "SÃmbolo")]
public string Symbol { get; set; }
This way, when I render my screen, it comes in Portuguese:
#Html.LabelFor(model => model.Symbol)
But...
As I am using Model First EF for my project, classes are constantly been changed by a T4 DbContext Generator. That way I can't use Display attribute, as it will be overwrited.
A solution given here is to extend partial classes automatically created. Kinda clumsy for me.
So my idea is to change the T4 script to get Documentation.Summary attribute from the EDMX model and add it as a Display Name attribute.
I found an article where someone explains how to extract this data, but I'm not succeding in making it work on DbContext Generator.
Has someone ever made this? Do you guys have better ideas?
Thanks!
few days ago i read tutorial about GenericRepository and Unit Of Work patterns http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application. I use web forms and i have EntityFramework CTP4 package installed. (I can't using EF 5).
I want to code generic repository for my project but i was stuck at this line:
this.dbSet = context.Set<TEntity>();
I know that this line doesn't work because a use ObjectContext in my project and database first approach. How can i deal with it? Can I code generic repository without migration to code first (which is not an option in my case) ?
This is the equivalent for ObjectContext:
this.dbSet = context.CreateObjectSet<TEntity>();
Now this creates an ObjectSet<TEntity> rather than a DbSet<TEntity>, but for your pattern you can use it in the same way.
UPDATE
The ObjectSet class does not have a utility method like that matches the Find() method of the DbSet. In order to "Get by key" you would need to construct an EntityKey and use the ObjectContext.GetEntityByKey(), unfortunately that's not a really simple thing to do.
There really isn't a simple way to tackle this, that I've found. In my case what I've done is to base all of my entities from a common class (using custom T4 templates to generate the classes from the model). And then I can add a generic constraint to my repositories, like:
public class MyRepository<TEntity> where TEntity : MyEntityBaseClass
And then my common base class has an Id field which is inherited by all the entities so I can can simply do:
return myObjectSet.SingleOrDefault(x => x.Id == myId);
I'm sure there are other approaches, that might be a good topic for another question.
1. You want to add the DbContextGenerator template to your visual studio templates:
2. After this make sure you clear out the default generation tool on your .edmx file.
3. Now you can implement the GenericRepository pattern as you wish.
Namespaces are really useful and PHP had no support for them until the recent few releases, AFAIK.
When I'm using Zend Framework, I have to remember long names with underscores - like Zend_Form_Element_Button or Zend_Form_Decorator_HtmlTag and so on.
If I use namespaces, this might be possible, and so much easier:
namespace Zend {
class something {
// ...
}
}
namespace Zend\Form {
class something {
// ...
}
}
namespace Zend\Form\Element {
class Button {
// ...
}
}
And to use it I do this:
use Zend\Form\Element\Button;
$btn1 = new Button();
So my question is, is it trivially possible, given the autoloader system and a lot of meta-class "black magic" that lives inside Zend Framework, to rewrite the structure of the code using namespaces, and then have more sensible class names?
The problem is not the length of the class names - Eclipse/Netbeans/Aptana handle that very well, it is the irritant that long names are.
Tends to get confusing after some time if some classes you use have similar parts in the names.
Since ZF is open source licensed, I don't think Zend would mind a namespaced version of the code, if mere renaming and some re-organization of code can achieve that.
Not trivial, no.
Matthew Weier O'Phinney wrote a blog about some of the issues ZF will have to face if and when they refactor the code to support PHP 5.3 namespacing:
http://weierophinney.net/matthew/archives/181-Migrating-OOP-Libraries-and-Frameworks-to-PHP-5.3.html
Abstract is a reserved word in PHP.
The same goes for interfaces. Consider
this particularly aggregious example:
namespace Zend::View
abstract class Abstract implements Interface
{
// ...
}
We've got two reserved words there: Abstract and Interface.
The Zend Framework is full of classes named Abstract and Interface. They're going to have to make a large number of backward-incompatible refactoring changes to make the ZF code support namespaces.
Also since backslash is a metacharacter in strings, any code that dynamically loads classes based on classname, such as Zend_Db::factory() or Zend_Filter_Input, is unnecessarily difficult to implement, because of the hare-brained decision the PHP core team made, using backslash as the namespace separator.