Forum Replies Created
But your SQL does more. It would also find lines in Load that have an associated row in Master with a null value in column AField. So your AField mustn’t be nullable so that the SQL is correct by chance. A “Not exists” query would be correct, but maybe a bit slower.
In OCL you could do: Load.AllInstances->select(x|x.Master->IsEmpty) where x.Master is the association from load to Master. This is much clearer than your SQL.
First, you should ask your question on stackoverflow with tag mdriven because this forum has actually moved there.
When trying to understand your question, I find some things to be unclear:
1) Maybe I’ve forgotton too much about SQL, but I think that your SQL does other things than you tell. You load Load data rows that have joined rows in Master having a null value in AField. In my understanding you don’t really need the left outer join. A inner join would do the same. Correct?
2) MDriven is not SQL. Doing mass updates is no typical task for ORM tools. The best answer for your question could very well be to simply do it in SQL, just depending on your system architecture.
3) If you want to do it with MDriven, you have to take into account how big your tables are. OCL only makes sense on small tables (maybe like <50000 rows) because it loads the complete table and filters in memory. If you have more rows you have to execute your query “in PS” which means that the query is generated as SQL. You can achieve the same using LINQ.
4) Depending on the change that you want to do, you have to load all objects that have to be changed, change the objects and update the database with these changes.
When I use an EcoSpace for testing, I don’t use the normal EcoSpace. I use a TestEcoSpace that is configured using a PersistenceMapperMemory. And: PersistenceMapperMemory supports external IDs perfectly. You only have to update the database as you would do for an ordinary EcoSpace after creating data in the EcoSpace.
I’ve made very good experiences using SpecFlow (behavior driven development) by using Gherkin and entering test data in a table form.
And when I try to write this as PSQuery I end up with:
PSQuery<CLass1>().Where(x => x.A1 == valueA1 && x.A2 == valueA2).SelectMany(x => x.Class2s).ToList();
which does not work because SelectMany is not implemented (see also https://www.capableobjects.com/forums/topic/selectmany-in-psquery/).
In OCLPS, I would write:
Class1.AllInstances->Select((A1=valueA1) and (A2=valueA2)).Class2s
But how can this be written as PSQuery?
I wanted to wait for an answer of Hans to get it confirmed because we also have this use case. In my understanding is shows as follows: As PSQuery translates to OclPs and the functionality does not exist for OclPs, it also can’t be done in PSQuery. At least for now.
Our work around is a method, that builds up a expression containing many ORs instead of a IN (..). We can so stay in PSQuery and don’t have to use the SqlPassthrough.
I’ve also experimented with a PersistenceMapperMultiDb some years ago. The findings were exactly as Hans wrote.
Our solution finally was to develop an EcoSpaceCollection EcoService. This EcoService is registered into an EcoSpace like any other EcoService and can store as many other EcoSpaces as you want. So we only need to pass the main EcoSpace as a parameter and the other EcoSpaces are contained as sub EcoSpaces within the main EcoSpace.
- This reply was modified 3 years, 1 month ago by Peter Buchmann.
maybe check one thing: I once had a similar problem: I created a lot of objects within a method (or was it a derived property) of an other object. That led to a huge number of subscriptions and these subscriptions took a long time to evaluate. Alternatively I got an OutOfMemoryException.
I just realized, that the Fakes framework is only part of Visual Studio Enterprise edition and is not available in the Community and Professional edition. But it seems that there are free alternatives like Prig and other commercial alternatives.
I see two problems:
1) Derived properties and derived associations: Sometimes they can get complex and you have to inject quite a lot of objects so that the desired value is set up correctly. Here it would be nice to be able to set the desired value directly.
2) The problem with the methods is indeed more complex. But while I read your answer I remembered the MS Fakes framework and indeed this framework could solve both problems.
In your test project, right-click on your MDriven model assembly and call “Add Fakes assembly” (https://msdn.microsoft.com/en-us/library/hh549175.aspx). Visual Studio now creates a fake assembly that supplies you with shims and stubs around each property and method that you can use to redefine the functionality of each method. I would say that this is a quite rude way of mocking, by far not so elegant like mocking interfaces and hardcore TDD developer would call this bad practice, but it works fine for situations like here.
It’s not the mainstream way to solve the mocking problem but it is quite ideal for setting up the environment while testing MDriven models. Maybe I could supply you with an example so that you can write a demo post. I tested this framework some years ago and have to dig in a bit again. But I think it should work.
As I first heared about TDD, I had the same feeling that you stated above. This changed gradualy within the last years. My understanding now is:
* DDD is about understanding the domain and building a system from this knowledge. By using MDriven we are able to generate this code functionality in a predefined and proven way. So the code that is generated by MDriven does not need additional tests just like XAML or Windows Forms generated code does not need tests. It just fulfills our needs.
* TDD is just the opposite approach. It states that you need tests to prove that the requirements are met by the code that you write on your own. When writing code by hand, you can make a lot of mistakes. TDD developers need the tests to get the same quality that we MDriven users already have.
But when using MDriven, there can still be a lot of code that is not generated, that a developer has to write on his own. For this code, it would be helpful when tests could be written as easy as possible.
So, how could tests be made easier in MDriven? I first thought about mocking interfaces or virtual classes like it’s usually done in TDD. But when thinking a bit further I got a different idea:
It’s all about decoupling the single parts of the system so that they can be tested independently.
* In common development stategies the main problem is to decouple the database from the system. In MDriven this is no problem at all. Take an EcoSpace with memory persistence and you are done. Using a repositiory is often the means how this is done commonly but I would never use a repository when using MDriven as MDriven is better than every repository could be.
* When using a complex business model it would be helpful when attributes and associations especially when they are derived could be mocked. Then one would not need to build up the complete underlying structure to get a derived value deliver a desired value. But here the MDriven cache could help. It should be possible to develop a specific ICache service for tests that would cache a mocked value for any feature. Then a test could set up this feature to return this specific value to decouple a class from its neighbours.
* Decoupling methods can’t be done with MDriven functionality. If the class is not sealed, it could be subclassed (e.g. with mocking tools) to change the functionality of virtual methods. The challenge would then be, that the EcoSpace would have to accept this subclass instead of the real class.
Would this be possible to implement and would this idea then really work? What do you think?
TDD means that you may only write one line of productive code (in opposite to test code) if you have written a failing test first. The new line of code makes the test green. So you get 100% code coverage. But TDD only tests own code and not frameworks.
In strict TDD you need test code also for generated code. So a TDD compliant code generator should also generate test code for the generated code. Only then you can correctly calculate your test code coverage (or if generated code is attributed with [ExcludeFromCodeCoverage]).
I myself am no TDD guy but I see the value of a high code coverage and I’m searching the best way how MDriven model methods could be tested. So I want to test the gist how you call it.
An EcoSpace implements the interface IEcoServiceProvider. So a test could be done like:
var ecoServiceProvider = new Mock<IEcoServiceProvider>(); // using Moq var sut = new EcoObject(ecoServiceProvider.Object); sut.TestMethod(); Assert.AreEqual...
When the method TestMethod() uses EcoServices, they could be set up in a way to return mocked objects but this is quite complicated to setup. One more problem is the tight coupling of the model objects so that associations to other objects can’t be mocked.
The other way is to use a EcoSpace with memory persistence so that no database access happens. But it still stays quite complicated.
So, when thinking about increasing testability of MDriven generated code, I think about following change: All features (properties and associations) and methods could be generated as virtual so that they could be mocked but I’m unsure about possibly negative side effects. What do you think?
PS: An interesting discussion to TDD can be found here: http://martinfowler.com/articles/is-tdd-dead/
OK, so the 15 to 30ms are the time needed for the activation of the EcoSpace. I understand. I think we have a custom EcoService registered that could take this time. Thank you for the clarification!
I assume that the EcoSpaceManager Pool that you mention can be switched on via
setting EcoSpaceManager.UsePool to true. This then uses a EcoSpaceStrategyHandler to do the pooling. With activating this, all objects in the EcoSpace (not only dirty ones) get serialized an deserialized for the next request.
The EcoSpaceManager only takes about 30 ms to create an EcoSpace. That’s quite OK for our usage scenario. But I can imagine scenarios where this is too long. In such cases one could think of creating a bunch of EcoSpaces prior to the usage with an async process so that an incoming request just can pull a prepared EcoSpace from a pool. But I assume that this is not what the EcoSpaceManager does and would need some additional custom logic.
your post is very general.
I think you can implement any architecture you design also using MDriven. Especially complex architectures like n-tier architectures are already in the box and turnkey is unique.
We use VS2012, TFS, MDriven and ReSharper but we might not be representative as we develop a app which is only used within our company and does not need to sell itself. We use a host DB2 database and our largest table increases by 300000 lines each day since some years.
Our app consists of a Winforms client, some 30 console apps, a small asp.net MVC app and a webservice component that is used by our components and other internal apps via a esb. But we also have a lot ancient COBOL host jobs. MDriven fits perfectly into such a mixed environment which is not very usual as of today.
If you meant architecture as custom MDriven extensions, I could also describe some of our extensions.