We have a lots of Entity and we are trying to limit the number of SQL objects generated by CodeFluent Entity. We are using some lightViews but I have the feeling that a lot of generated views are useless.
Is it possible to decide Entity by entity to produce view or not ? (I'm aware of the produceViews option on the SQL producer but we still need some views)
No this is not an option. The produceViews attribute only related to persistent views explicitly defined in your model.
Now : if you are completely in control of what you can use, sure you are not referencing some default generated views in any model attribute, any methods (CFSQL or raw SQL), or partial code, then here some ideas :
You can choose not to use the default generated xx_views.sql :
- do not keep it in sourcecontrol
- provide your own views (the persistent known ones extraceted from the generated file) in a custom post SQL script after_[DefaultNamespace]_views.sql : in it you could for instance delete all existing views, then declare only the ones you want to use. It would be a manual step that can be time consuming if your persistent views are changing a lot between versions. May be a good name convention for persistent views will help this manual report for a good enough solution.
Another more advanced and cleaner idea would be to provide a custom aspect removing the "default" view created for each entity in the meta model before production (see infered meta model and CodeFluent.Model.Entity class), except for entities marked with a custom attribute. This is an idea not guaranted/tested.
Related
Is it possible to define navigation properties between Views in EF with code first? Please, note that I do not need any tool generating any code for me. I would like to know whether or not this can get done and the logic behind this.
Suppose you have a project in which you will only work with views. No data will be created, updated or deleted (at least by you). All you need to do is queries and all you have are views.
Suppose now a second scenario in which you can also have tables, but your purpose is only to visualize data (you will treat them as views). However, there is not always a foreign key referencing the primary key of the parent table in relationships.
My question is: Can I define navigation properties in these scenarios? Or do I have to relay on joins only?
Thanks!
I'm working on this myself. Everything I'm reading indicates you have to manually edit the .edmx files so that the views are considered tables and manually add the nativation properties yourself. Downside is if you resync against the database you have to repeat the process all over again.
Re:
https://social.msdn.microsoft.com/Forums/en-US/dcbdfe52-6ba7-4e75-94aa-51c88b57635c/adding-navigation-property-to-a-view?forum=adodotnetentityframework
I have been tasked with fixing a number of bugs on existing application that makes use of JPA (EclipseLink).
In this application it common for there to be multiple entities that indirectly share the same table via SQL views. As an example, I might have a entity called TEmployeeInfo and another entity called VActiveEmployeeInfo. While the first maps to a table directly, the second maps to a view of the same table as the first.
This seems like it would cause issues with caching as any updates using the first entity (table) would not be immediately available in the second (view).
Are my suspicions correct?
If so, what are some possible steps to correct this short of refactoring a large portion of the application?
If the same rows are mapped twice, then the cache can become stale if the objects are updated. You can have both classes use the real table, or perhaps use inheritance.
Otherwise, you can disable the shared cache of this class.
http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F
We develop the back office application with quite large Db.
It's not reasonable to load everything from DB to memory so when model's proprties are requested we read from DB (via EF)
But many of our UIs are just simple lists of entities with some (!) properties presented to the user.
For example, we just want to show Id, Title and Name.
And later when user select the item and want to perform some actions the whole object is needed. Now we have list of items stored in memory.
Some properties contain large textst, images or other data.
EF works with entities and reading a bunch of large objects degrades performance notably.
As far as I understand, the problem can be solved by creating lightweight entities and using them in appropriate context.
First.
I'm afraid that each view will make us create new LightweightEntity and we eventually will end with bloated object context.
Second. As the Model wraps EF we need to provide methods for various entities.
Third. ViewModels communicate and pass entities to each other.
So I'm stuck with all these considerations and need good architectural design advice.
Any ideas?
For images an large textst you may consider table splitting, which is commonly used to split a table in a lightweight entity and a "heavy" entity.
But I think what you call lightweight "entities" are data transfer objects (DTO's). These are not supplied by the context (so it won't get bloated) but by projection from entities, which is done in a repository or service.
For projection you can use AutoMapper, especially its newer feature that I describe here. This allows you to reduce the number of methods you need to provide "for various entities" (DTO's), because the type to project to can be given in a generic type parameter.
I have an Entity called "Product", this entity, through table mapping, merges 6 tables that have a 1 to 1..0 relationship with "Products". This all works wonderfully. There is another property I want to add to "Products", which is sBBR_rate, this value is not in a table that has a direct 1 to 1..0 relationship, it is related through a link table as below:
When I import the two tables into the EDM, I can't see a way in the "Mapping Details" of
"Product" to reference the sBBR_rate. I can reference RatesLink and link that to the "Products" primary key, however, I cannot reference the BBR table.
The methods I can think of to work "around" this is are as follows:
Create a view, reference the view in the EDM.
Create an SP and use a function import to retrieve the BBR when it is required.
Create a "Rates" entity in the EDM that can then draw down the sBBR_rate into it. Navigate to the Products BBR through Product.Rates.sBBR_rate.
Is there a better way I can do this that doesn't feel so much like a fudge? Perhaps by directly editing the XML of the Mapping or Conceptual layers of the EDM?
Thanks for your input.
Because the multiplicities on the Product -> RatesLink and RatesLink -> BBR relationships are 0 to 1, you should be able to access the sBBR_rate from a Product instance like this:
myProductInstance.RatesLink.BBR.sBBR_rate
I can see on the EDM screenshot that RatesLink has a Product and BBR property, which would indicate this should be available - is it?
On a side note, if it makes sense for the sBBR_rate property to commonly be accessed directly from Product, you might want to follow the law of demeter and create a property on Product which returns it directly.
The model we are using is to extend entities by using partial classes which we've found useful so we can get additional properties in the autogenerated classes (we are using a POCO T4 template to autogen but I believe this would work just as well with the default entity object generation).
So we would have
//.. this one is from the T4 template
public partial class Product
{
//.. all the autogenerated methods
}
and in a separate file that isn't autogened
//.. now in a separate file created by me
public partial class Product
{
//.. my custom properties and methods to make the entities more usable
public string BBRRate
{
get {return this.RatesLink.BBR.sBBR_rate; }
}
}
This means that I can just do
myProduct.BBRRte
I know there are other ways to do this by amending the edmx file but this one we found easy to implement. You just need to watch performance because you are potentially loading extra data. Also we did this with LazyLoading turned on but with more work you wouldn't have to
We also experimented with hooking into the ObjectMaterialized event in the ObjectContext class to preload some of these properties. Using a custom interface i.e. IMaterialisable we could check if the object was of that type then call a method (Materialise) to prepopulate some of the properties. This seems like a good idea but we didn't widely use it - it was easy to load up too much stuff. If you do the load on the properties in the partial classes then it becomes more efficient. Just my experience.
Anyway - as always an interesting question and good luck again with your dev.
EDIT
There is a rule that everything in the store layer must be represented some way in your conceptual layer. Therefore removing the tables from the conceptual layer but bring through some of the properties I don't think will work in it's gross form. Therefore I can think of two further options
Create a View on the database and bring that in as you have already mentioned. TBH this is what I would do.
Use the DefiningQuery element directly in your xml (the store layer) and map the query through to a custom entity of your exact design. Julie Lerman describes this as the ultimate escape hatch for Entity Framework.
Remember though - if you manual amend the XML in point 2 then you lose the ability to automatically update the module through the IDE
I ended up creating a view and then linking this view in the EDM, this worked a treat.
I would like to experimentally apply an aspect of encapsulation that I read about once, where an entity object includes domains for its attributes, e.g. for its CostCentre property, it contains the list of valid cost centres. This way, when I open an edit form for an Extension, I only need pass the form one Extension object, where I normally access a CostCentre object when initialising the form.
This also applies where I have a list of Extensions bound to a grid (telerik RadGrid), and I handle an edit command on the grid. I want to create an edit form and pass it an Extension object, where now I pass the edit form an ExtensionID and create my object in the form.
What I'm actually asking here is for pointers to guidance on doing this this way, or the 'proper' way of achieving something similar to what I have described here.
It would depend on your data source. If you are retrieving the list of Cost Centers from a database, that would be one approach. If it's a short list of predetermined values (like Yes/No/Maybe So) then property attributes might do the trick. If it needs to be more configurable per-environment, then IoC or the Provider pattern would be the best choice.
I think your problem is similar to a custom ad-hoc search page we did on a previous project. We decorated our entity classes and properties with attributes that contained some predetermined 'pointers' to the lookup value methods, and their relationships. Then we created a single custom UI control (like your edit page described in your post) which used these attributes to generate the drop down and auto-completion text box lists by dynamically generating a LINQ expression, then executing it at run-time based on whatever the user was doing.
This was accomplished with basically three moving parts: A) the attributes on the data access objects B) the 'attribute facade' methods at the middle-tier compiling and generation dynamic LINQ expressions and C) the custom UI control that called our middle-tier service methods.
Sometimes plans like these backfire, but in our case it worked great. Decorating our objects with attributes, then creating a single path of logic gave us just enough power to do what we needed to do while minimizing the amount of code required, and completely eliminated any boilerplate. However, this approach was not very configurable. By compiling these attributes into the code, we tightly coupled our application to the datasource. On this particular project it wasn't a big deal because it was a clients internal system and it fit the project timeline. However, on a "real product" implementing the logic with the Provider pattern or using something like the Castle Projects IoC would have allowed us the same power with a great deal more configurability. The downside of this is there is more to manage, and more that can go wrong with deployments, etc.