Having created a standard Silverlight Business Application in VS2010 and set up a model from a SQL Server database, I have various entities and associations, among which AssetGroup and Asset are in a 1:m relationship.
Allegedly I can use dot notation to get the associated AssetGroup out of an asset instance. Through the modern miracles of deferred execution and lazy loading, I am assured, my data will be delivered the very moment that I need it.
But it doesn't work.
What are the required incantations, and do I have to slay a chicken or a goat?
This looks promising. As soon as I've tried it out I'll update.
In the question I mention a blog post containing a possible solution. That solution works, but entails changes to generated code, which is obviously as fragile as a solution gets.
Here's a robust way to apply the solution: change the code generator.
On the EDMX designer surface right-click for the context menu and choose Add Code Generation Items...
Try to improve on "Model1.tt" as a name and save the TT file.
Open the TT file.
Search for "return (" to directly find the method template you need to change.
Edit as shown.
Rebuild the solution.
Change this
return /* big hairy expression */;
to this
var entity = /* big hairy expression */;
if (!entity.IsLoaded) entity.Load();
return entity;
Related
I am building simple crud for an entity. Initial state is read on particular entity(key) using view>form.bindElement('/entity(key)').
when I click on new button I clear the form and when the cancel button is clicked during the new/create process(without performing the save), how to go back to the previous entity. Is there some place ui5 stores, the previous entity or should I have some variable and assign it to the controller.previousEntity = oldsPath?
what are the different members in the oModel,it start with
a(aBindings)
b(bUseBatch)
m(mContexts)
o(oHeaders)
p(pCallAsync)
s(sPathUrl).
Is there a naming convention in these?
From what I can see, there are following things you need to notice and work upon.
Its generally not a good idea if you use the same form to display and to create/update also. A simpler approach would be to
use a new popover to show the form for create and in that case, the view binding would not be changed when you cancel the operation.
However, if you still want to use the same form, yes you would have to bind the view/form again on cancel operation. You can have a variable declared in the Component.js to store the path for you. In UI5, the model captures the current state to ensure the back the binding concept by default.
You can check all properties and their definitions here: oData Model
Yes, there is a naming convention followed here.
a - Array, s-String, b- Boolean etc.
Read more about Hungarian notations for naming conventions
The previous entity is still there in the cache (ODataModel.oData), but you'll need to re-bind it. For that purpose, as you have written, you'll need to store the path to the entity yourself. Once you bind the control, I don't think the previous binding context is stored somewhere (why should it).
From the diagram on page 570 of the UML spec I concluded that a Lifeline should have the events property, holding an OrderedSet(OcurrenceSpecification). Unfortunately it is not there, at least in the QVTo implementation that I use.
All I have is the coveredBy property, serving me with an (unordered) Set(InteractionFragment). Since my transformation relies on the correct order of MessageOcurrenceSpecification I somehow need to implement myself what I expected to be implemented by the missing events property.
This is what I have so far:
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.coveredBy->selectByKind(OccurrenceSpecification)->sortedBy(true);
}
Obviously sortedBy(true) does not get me far, but I don't know any further. Who can help?
All I could find so far were other people struggling with the same issue years ago, but no solution:
https://www.eclipse.org/forums/index.php/m/1049555/
https://www.eclipse.org/forums/index.php/m/1050025/
https://www.eclipse.org/forums/index.php/m/1095764/
Based on the answer by Vincent combined with input from a colleague of mine I came up with the following solution for QVTo:
-- -----------------------------------------------------------------------------
-- Polyfill for the missing Lifeline::events property
query Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.fragment
->selectByKind(OccurrenceSpecification)
->select(os: OccurrenceSpecification | os.covered->includes(self))
->asOrderedSet();
}
I don't know if it is possible, using directly coveredBy to get an ordered collection. As coveredBy is unordered, if you access it directly by the feature, you will have an unpredictible order and if you try to access it using the eGet(...) stuff, the same result will occur.
However, if I understood correctly, there is a "trick" that could work.
It relies on the assumption that each OccurrenceSpecification instance you need is held by the same Interaction that contains the Lifeline and uses the way EMF stores contained elements. Actually, each contained element is always kind of 'ordered' relatively to its parent (and for each collection so EMF can find elements back when XMI references are expressed using the element position in collections). So, the idea would be to access all the elements contained by the Interaction that owns the lifeline and filter the ones that are contained in coveredBy.
Expression with Acceleo
This is easy to write in MTL/Acceleo. In know you don't use it, but it illustrates what the expression does:
# In Acceleo:
# 'self' is the lifeline instance
self.interaction.eAllContents(OccurrenceSpecification)->select(e | self.coveredBy->includes(e))->asOrderedSet()
with self.interaction we retrieve the Interaction, then we get all the contained elements with eAllContents(...) and we filter the ones that are in the self.coveredBy collection.
But it is way less intuitive in QVT as eAllContents(...) does not exist. Instead you have to gain access to eContents() which is defined on EObject and returns an EList which is transtyped to a Sequence (in QVT,eAllContents() returns a ETreeIterator which is not transtyped by the QVT engine).
So, how to gain access to eContents() in the helper? There is two solutions:
Solution 1: Using the emf.tools library
The emf.tools library give you the ability to use asEObject() which casts your object in a pure EObject and give you more methods to access to (as eClass() for example...etc).
import emf.tools; -- we import the EMF tools library
modeltype UML ...; -- all your metamodel imports and stuffs
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.asEObject().eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}
Solution 2: Using oclAstype(...)
If for some reason emf.tools cannot be accessed, you can still cast to an EObject using oclAsType(...).
modeltype UML ...; -- all your metamodel imports and stuffs
modeltype ECORE "strict" uses ecore('http://www.eclipse.org/emf/2002/Ecore'); -- you also register the Ecore metamodel
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.oclAsType(EObject).eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}
Limitation
Ok, let's be honest here, this solution seems to work on the quick tests I performed, but I'm not a 100% sure that you will have all the elements you want as this code relies on the strong assumption that every OccurrenceSpecification you need are in the same Interaction as the Liteline instance. If you are sure that all the coveredBy elements you need are in the Interaction (I think they should be), then, that's not the sexiest solution, but it should do the work.
EDIT>
The solution proposed by hielsnoppe is more eleguant than the one I presented here and should be prefered.
You are correct. The Lifeline::events property is clearly shown on the diagram and appears in derived models such as UML.merged.uml.
Unfortunately Eclipse QVTo uses the Ecore projection of the UML metamodel to UML.ecore where unnavigable opposites are pruned. (A recent UML2Ecore enhancement allows the name to be persisted as an EAnnotation.) However once the true property name "events" has been pruned the implicit property name "OccurrenceSpecification" should work.
All associations are navigable in both directions in OCL, so this loss is a bug. (The new Pivot-based Eclipse OCL goes back to the primary UML model in order to avoid UML2Ecore losses. Once Eclipse QVTo migrates to the Pivot OCL you should see the behavior you expected.)
I am seeing something in Entity Framework that has me thinking that I either completely misunderstand how the database context works, or EF is actually broken (and I know that most likely means I just don't get it).
Consider the following scenario:
In the database I have a bunch of Student Attendance records, and they all have a code marked as P for present.
Then we have something akin to the following:
public void SetAttendance(int dayId,int attendanceId, int attendanceId, String mark)
{
updateAttendance = new StudentAttendance()
{
Code=String.Empty,
AttendanceId=attendanceId,
DayId = dayId
};
context.Attach(updateAttendance);
//I don't save changes yet because I now need to do some logic
var markedAttendanceCount = context.StudentAttendance.Where(att=> !String.IsNullOrEmpty(att.Code) && att.DayId == dayId).Count();
var allAttendanceCount = context.StudentAttendance.Where(att=> att.DayId == dayId).Count();
var updateDay = new ClassDay()
{
DayId = dayId,
AllMarked = markedAttendanceCount = allAttendanceCount
};
context.Attach(updateDay);
context.SaveChanges();
}
I would expect that if I were to call that SetAttendance method as follows:
myworker.SetAttendance(10,20,String.Empty);
That it should properly recognize that the attendance for the day is not fully marked. What I am instead seeing is that my look int query against context.StudentAttendance is asking the database. As such, my detection of the day's status change is always one behind.
I thought that the context was basically supposed to be smart enough to let you write something like this. In essence, I had always had the impression that the db context lets you essentially work with a serializable transaction kind of behavior. As you make changes to the data through your context, those changes will reflect in queries against the context. Am I missing something?
EF doesn't work that way, no. For performance reasons basically.
However, context.StudentAttendance.Local exposes a set containing the added entities. It also contains any entity previously loaded by the context in a query. If you like you can load the whole DbSet into memory as described here: https://msdn.microsoft.com/en-au/data/jj592872.aspx however this is not advisable for large datasets.
Also, you should be using context.Add() rather than context.Attach(). The latter is for entities which already exist in the database.
It's true that you don't fully understand how EF works, but I think EF is to blame for that. You're asking a very good and valid question.
NHibernate, as opposed to EF, has this AutoFlush feature. This means that "at any moment" it may commit changes to the database in order to keep local changes and database content in sync without the developer's intervention. In your case, it would have saved the new StudentAttendance before querying existing ones from the database. So if the new one matched the predicate (DayId == dayId) it would have contributed to allAttendanceCount. This feature, when understood well, allows for a very intuitive way of dealing with data, exactly the way you expected EF to behave.
The truth is, however, that AutoFlush has always eluded developers, so they often just disabled it. As a developer you want to have full control, you don't want to depend on some smart feature that seems to have a life of its own. (Even though the reality is that you probably just didn't take the time to fully get it).
I can imagine that for this reason, the EF team decided not to implement such a feature.
So what to do in your case? Not easy. When after adding the new StudentAttendance you'd do...
context.StudentAttendance.Load();
(assuming that you have a DbContext, though your "context.Attach" doesn't seem to be in line that).
And then...
var allAttendanceCount = context.StudentAttendance
.Local // <= Local! Includes the new item
.Where(att=> att.DayId == dayId)
.Count();
...you'd have the desired result. But of course, loading all StudentAttendance records locally is a tremendous overkill.
One simple alternative is to to the count as you do now and add 1 to it.
Another alternative is to mimic autoflush, sort of, and save the new StudentAttendance before doing the count. But then you'd have to wrap everything in a TransactionScope. One advantage is that you'd have the very latest value of allAttendanceCount.
Edited for Clarity
I've been looking at ORMs for the last week, as well as trying to decide if I want to bother with them. At the end of the day, there seem to be about a dozen worthy contenders, of which most are fairly hard to tell apart. I eventually settled on the potential trio of EF, OrmLite and PetaPoco, all of which seem pretty good.
One feature I've been looking for is the ability to magically configure the code generator to automatically right trim all strings in the generated POCOs, without any changes to the DB. I have a database with literally thousands of records spread across hundreds of fields, and every single string field has a bunch of spaces at the end of it for legacy reasons. Those need to be stripped from the resulting POCOS/Entities to make the processing less ugly, but I can't make any changes to the DB (it's not mine), so I'm wondering if there is easy-easy way to do it.
With Entity Framework I looked a little bit at the process for Database First and Model First design, and those look like you could probably tweak the T4 template code to generate appropriate code on a case by case basis. This seems like it would be viable, but I don't want to reinvent the wheel if someone has already done it. I would just like to have the code that takes care of the problem.
For the other ORMs, I could probably pull them in the house, figure out how they work and plug-in some kind of logic that does the magic.
So does anybody have a suggestion for an ORM that has a configuration switch that can automatically right-trim all strings? It would make the database much easier to work with, hundred percent certain there is never any value in those extra spaces at the end.
Thought this was a good feature so I've just added this to ServiceStack.OrmLite where you can now add a custom filter for strings, e.g:
OrmLiteConfig.StringFilter = s => s.TrimEnd();
public class Poco
{
public string Name { get; set; }
}
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<Poco>();
db.Insert(new Poco { Name = "Value with trailing " });
var row = db.Select<Poco>().First();
Assert.That(row.Name, Is.EqualTo("Value with trailing"));
}
It will be in the next v4.0.19+ NuGet release of ServiceStack, which is now available on ServiceStack's MyGet Feed.
With Entity Framework (and possibly PetaPoco which I don't know personally) you should be able to modify the T4 template and add read-only properties to your entities, returning the trimmed value of database-related property.
public string Name
{
get { return this.DbName.TrimEnd(); }
}
But...
You have to find a way to do this for string properties only (I think one of the methods that are visible in the T4 template can be used for that, but I'm not sure).
Modifying T4 templates is something you may have to do again when updates are released.
You can't use the read-only properties directly in LINQ-to-entities because EF can't translate them into SQL. You'll alway have to use them after an AsEnumerable() call.
What is a valid reason for using the 'ADO.NET EntityObject Generator' with EF? In case you don't know, it generates a T4 file that does the building of the entities from the edmx. You can then change the T4 file to change how the entities are generated.
My question is: other than changing the base class in which entities are derived (also implementing interfaces) and changing the accessibility of entities and/or the context objects and naming conventions, what use does this have? Considering the existing features of EF and partial classes.
I've come up with 2
Grab the table/column descriptions from the database and populate the summary on the entities and properties
Generate light wieght DTO's and do auto mapping.
1 seems like too much work considering it only updates the comments on the models, not the edmx itself (although it could do so)
2 Is this even useful?
We have done a few things with the T4 templates. The first one is to split out the generated code into one class per file, instead of one massive file. This just makes it easier to navigate and browse through the entities.
The second, and more important one, is to automatically generate data annotation validation attributes such as StringLength and Required. This lets us validate our entities with a single function call, and it makes sure that their validation attributes are always in sync with the database (since if we change a column length in the DB, for example, the generated StringLength() attribute is then updated when we do 'Update model from database').
At a previous job, we also added base classes and interfaces to the entities, as you mentioned in your question.
Here's a snippet from our T4 template that checks for required columns and string lengths and adds the necessary validation attributes:
''' <summary>
''' <#=SummaryComment(primitiveProperty)#>
''' </summary><#=LongDescriptionCommentElement(primitiveProperty, 1)#>
<EdmScalarPropertyAttribute(EntityKeyProperty:=<#=code.CreateLiteral(ef.IsKey(primitiveProperty))#>, IsNullable:=<#=code.CreateLiteral(ef.IsNullable(primitiveProperty))#>)>
<DataMemberAttribute()>
<#+
' begin required attribute
If Not ef.IsNullable(primitiveProperty) and not ef.IsKey(primitiveProperty) then
#>
<#+
If ef.ClrType(primitiveProperty.TypeUsage) = GetType(Guid) Then
#>
<GuidRequiredAttribute(ErrorMessage:="<#=FixName(code.Escape(primitiveProperty))#> is required")>
<#+
Else
#>
<RequiredAttribute(ErrorMessage:="<#=FixName(code.Escape(primitiveProperty))#> is required")>
<#+
End If
#>
<#+
End If
If HasMaxLength(primitiveProperty.TypeUsage) then
Dim d = MaxLength(primitiveProperty.TypeUsage)
#>
<StringLengthAttribute(<#=d#>, ErrorMessage:="<#=FixName(code.Escape(primitiveProperty))#> cannot be longer than <#=d#> characters")>
<#+
End If
#>
Well, the reason is that you can do anything with it. So, why don't have it? Of course the usage of T4 is very limited to some special cases, and most of the time it doesn't make sense to use it. On the other hand you can do funky stuff with it. For example you can define some user defined stuff. Let's say you have a Sort column in your table. Then you could define a query function where it automatically sorts every entry if this column exists. Maybe too trivial for an example, but there are tons of other weird architectures where it makes much more sense.
You can also make use of other code generation stuff, without EF. So it's certainly here for completeness and extendability.
T4 template replaces custom tool used in EFv1 to generate code behind file (.designer.cs file with all classes). The main advantage of T4 is that you can change it per project just by modifying text .tt file. In case of custom tool changes were mostly impossible.
With T4 you have complete control over entity classes generated from your EDMX. It is transformation of EDMX into C# or VB.NET files. The default template creates class files with features required by most of developers but if you need anything else you can simply go to your .tt file and add it.
Possibilities for changes are unlimited because EDMX file itself is extensible. On behind EDMX is just XML file and you can include your own custom XML elements in this file (it has some restrictions but it is possible - here is some example for SQL generation in model first approach). Once you have custom elements in EDMX you can use them in T4 template as decision logic for additional features you want to include in generated code. Entity designer is also extensible - you can create custom extensions which will be stored as custom elements in EDMX file. Both EDMX and Entity designer extensions are nicely described in book Entity Framework in Action.
I know this is an old question, but I would have liked to come across this information when I started out.
In our case where we have a win32 Delphi client in our multi-tier solution, I've used the templates (in C#) to generate the DTO classes in .Net, and the win32 counterparts.
This allows us to encapsulate the CRUD functionality on the client using largely auto-generated Delphi code:
procedure Delete;
class function DeleteDto(const _dESPATCHID: integer) : boolean;
class function GetNextID : integer;
class function Get(const _dESPATCHID: integer) : TDtoDESPATCH; overload;
class function Collection(const __filterXml: string): TList<TDtoDESPATCH>;
function Load: boolean; overload;
function Populate(_primaryDict : TDictionary<string, Variant>) : boolean;
function Save : boolean; overload;
Change tracking from the client can also be automated, so each property setter will mark the changed property, to ensure only changed properties are updated.
For example:
procedure TDtoDESPATCH.SetSCT_STATUS(const value : string);
begin
if (self.IsLoaded) and (inherited SCT_STATUS <> value) then
begin
TrackChange('SCT_STATUS');
self.Modified:= True;
end;
inherited SCT_STATUS := value;
end;
On the server side, another template takes care of all the CRUD operations in an auto-generated WCF service that's also exposed as an asmx web service. The Interface, WCF methods and all annotations are generated from the template.
// convert to entity
var _entity = _dto.ToEntity();
if(exists)
{
Global.LogActivity(string.Format("{0} - profile {1}, updating DESPATCH: {2}", racID, profile, _dto.ChangedProperties ));
// Attach the entity to the db
db.DESPATCHes.Attach(_entity);
// Change tracking
ChangeTracking<DESPATCH>(_dto.ModifiedProperties, db, _entity);
}
In a scenario where WIN32 has to be part of the solution, hand coding all this would be a (worse) nightmare.
I've used them quite a bit to generate code that is useful to us at a Datalayer level.
Altering whether they implement additional contracts (interfaces), adding methods, annotations and in the case of a non-layered application (and NOT recommended beyond this) adding property changed notification.
By adding some of these items to the generation at the Datalayer, I've been able to use a template in the Model project to generate the boiler plate code at this level too.
Bottom line, if you can safely get the computer to code for you, then it's well worth while. In our case 80% of basic plumbing work can be code genned - if it's incorrect, it's generally very easy to fix and regenerate.