|
|
Comments and Discussions
|
|
 |

|
Hi, Code Project Team.
please view "Arkeos Factory" in www.multiclicksistemas.net (Spanish only for now).
"Arkeos Factory" generate code for "Arkeos Framework". Arkeos factory is based in Sample paradigm:
<big>blg.Post:</big>
{ $Post$Id! 12345
Blog_: MeBlog
Content_: This is y blog bla bla ............
.............
CreationDate: July 27/2009
Heading: My title.
isPublished_: Yes isActivate: Yes
<big>blg.Categories:</big>
{[NameCategories!]
[Technologies]
}
}
if Not exists (select * from sysusers where name = 'blg' ) then
grant connect, group, dba to blg
end if
go
if exists (select * from sys.syscolumns where tname = 'Post' and creator = 'blg') then
drop table "blg"."Post"
end if
go
Create Table "blg"."Post"
(
compania Integer Not null,
PostId Integer not Null ,
BlogPost Varchar(6) not Null ,
ContentPost Text not Null ,
CreationDate Date not Null ,
Heading Varchar(14) not Null ,
isPublishedPost byte not Null default 0,
isActivate byte not Null default 0,
fecha_impresion datetime null default timestamp,
fecha_reimpresion datetime null default timestamp,
fuente varchar(32) null default 'CP1865',
fecha_computador datetime null default timestamp,
usuario varchar(32) null default last user,
secuencia Integer default autoincrement,
Primary Key (Compania, PostId)
)
go
CREATE TRIGGER log_blg_Post AFTER INSERT, DELETE, UPDATE
ORDER 100 ON "blg"."Post"
REFERENCING OLD AS deleted NEW AS inserted
BEGIN
insert into DBA.auditorias (
tabla ,
appinfo ,
nuevoPKey ,
ViejoPkey ,
nuevoXml ,
ViejoXml )
values (
'"blg"."post"',
CONNECTION_PROPERTY ( 'AppInfo' ),
(select compania, postid from inserted as "key" for xml auto),
(select compania, postid from deleted as "key" for xml auto),
(select inserted.* from inserted for xml auto, elements),
(select deleted.* from deleted for xml auto, elements)
)
END
go
if Not exists (select * from sysusers where name = 'blg' ) then
grant connect, group, dba to blg
end if
go
if exists (select * from sys.syscolumns where tname = 'Categories' and creator = 'blg') then
drop table "blg"."Categories"
end if
go
Create Table "blg"."Categories"
(
compania Integer Not null,
PostId Integer not Null ,
NameCategories Varchar(12) not Null ,
fuente varchar(32) null default 'CP1865',
fecha_computador datetime null default timestamp,
usuario varchar(32) null default last user,
secuencia Integer default autoincrement,
Primary Key (Compania, PostId, NameCategories)
)
go
alter table "blg"."Categories"
ADD FOREIGN KEY fkey_blg_Categories_blg_Post(Compania, PostId)
REFERENCES blg.Post( Compania, PostId)
CHECK ON COMMIT
go
CREATE TRIGGER log_blg_Categories AFTER INSERT, DELETE, UPDATE
ORDER 100 ON "blg"."Categories"
REFERENCING OLD AS deleted NEW AS inserted
BEGIN
insert into DBA.auditorias (
tabla ,
appinfo ,
nuevoPKey ,
ViejoPkey ,
nuevoXml ,
ViejoXml )
values (
'"blg"."categories"',
CONNECTION_PROPERTY ( 'AppInfo' ),
(select compania, postid, namecategories from inserted as "key" for xml auto),
(select compania, postid, namecategories from deleted as "key" for xml auto),
(select inserted.* from inserted for xml auto, elements),
(select deleted.* from deleted for xml auto, elements)
)
END
go
with in code "Arkeos Factory" generate SQL Script for create tables, Referential Integrity, Visual Interface. Audit page, Inital Help Page, Auto Test,. Other simple language make easy your life for implement Bussines rules,
Please contactme for more information adrua@multiclicksistemas.net
Adalberto Raul Rua Aguirre
adrua@multiclicksistemas.net
modified on Thursday, July 30, 2009 10:29 AM
|
|
|
|

|
I don't agree with your reasons. Just because RAM is plentiful and processors are fast does not mean we should forget what we've learnt about efficient coding and efficient design. 4 bytes or storage memory has exactly the same effect, whether your total available RAM is 2GB or 640k.
Besides, I don't like code generation tools. I like to know that (as far as humanly possible) that I wrote every line of code in my application - or at least know exactly what it does and why it's needed.
|
|
|
|

|
You do have some good points but in some cases code generation is necessary...I'm sure you came across to the old ADO.NET typed dataset...or you can think of the designer code created behind a form or a control.
Any ORMs out there usually benefit from the use of code generation, and partial class are there also I'm sure for this reason.
I do agree however, that the article and the "database" application discussed here are more useful from the point of view of an embedded "OO Database".
I haven't check the code to be honest, but I appreciate the effort of putting this article together and I don't think it deserve such a low score, IMHO of course. I actually think it is a good article.
Keep up the good work.
modified on Thursday, July 30, 2009 8:15 AM
|
|
|
|

|
Hey Bilo,
bilo81 wrote: the article and the "database" application discussed here are more useful from the point of view of an embedded "OO Database".
Exactly. Actually, as it is now, ObjectLounge is not a database. It is a framework that handles the main features of a database (ACID). Only the "D" (durability) is not handled directly by the framework, and that's also the reason why it's not an ORM. It just triggers a layer that we call SyncProvider, which can do anything he wants, even using NHibernate or other ORMs. The SyncProvider simply gets the updated, inserted and deleted entities, and he has to the work then. By default, we use a very very simple SyncProvider that just dumps the serialized entities and their relations in a file.
Possible UseCases could be:
* You have a standalone client app and use ObjectLounge as an "embedded db".
* You want to have something like a modern DB: You can wrap your ObjectLounge domain model with a service layer to make data and functionalities available to others.
In future, we plan to implement a small hosting environment for domain models. This environment can be configured so that it automatically exposes Get and Set service methods for your model. Maybe this is then more like a DB (we are inspired a little bit of things like CouchDB, which just exposes a REST api).
Have a nice day!
P.S.: Thanks for the back-up
|
|
|
|

|
You are welcome, you did a very good job!
Regards
|
|
|
|

|
Graham Downs wrote: 4 bytes or storage memory has exactly the same effect, whether your total available RAM is 2GB or 640k.
I think this statement is not correct. I try to explain what we meant with the "Ram" thing: If you look back over 30 years, Smalltalk was invented, and it was revolutionary. It was dynamic, had a dynamic type system that could be reflected, you could do refactorings, it had relied on a virtual machine and it had a garbage collector. I was extremely productive for developing business apps due to setting the focus on abstract modeling and not on technical stuff. But it didn't establish in a wide range, because it was indeed a big problem having all these things running on the hardware those days. Graham, in a today's business application, if you care about having or not having 4 bytes, you waste the customer's money.
Graham Downs wrote: Besides, I don't like code generation tools.
Code generation / code modification is necessary if you want to express a pattern which is expressed not on a concrete level, but on a meta level (e.g. a pattern that adresses the type system) and that is not built in your programming language. Code generation is one way to achieve that, there are a lot of other ways to do that like code modification in dynamic languages, post compilers etc.
Graham Downs wrote: I like to know that (as far as humanly possible) that I wrote every line of code in my application
Why do you use frameworks at all? You use the .Net framework library and the CLR without having written the source code.
Graham Downs wrote: or at least know exactly what it does and why it's needed.
Why it's needed in general, I explain below. Maybe I can tell you a little bit about what we do:
* When the framework starts, we generate a runtime proxy for each of your entity classes.
* The proxy overwrites your property getters and setters.
* This is necessary for many framework's concerns. For example, it handles isolation aspects, rollback behavior (backing up property values in a running transaction), track changes (which is needed for validation and persistence) and other things.
Instead of using dynamic approaches like code generation, there is another way: Conventions! These conventions have to be implemented by the user of a framework. For example, if you want to use a framework, you have to implement certain interfaces, inform the framework when something happens in your code and so on. This means:
* a lot of extra work for the framework user.
* it is less robust, because it's not always possible for the framework to check if you fulfilled all conventions.
* You have to repeat yourself because of missing abstractions.
|
|
|
|

|
Great article! Love it! I re-created your demo using the sample code, and as an experiment, tried to bind the IList Authors property in the DomainModelContext to a Data Grid in WPF (using the data grid in the WPF toolkit). This worked well once I defined the columns.
The trouble arises when I double-click an item in the datagrid to edit it. I get the "'EditItem' is not allowed for this view" exception, which essentially means that WPF views the collection as Read Only. I also attempted to use BeginTransaction in the BeginningEdit event of the grid, and Commit transaction on the CellEndEditing event so I could wrap the edit into a transaction. I still received the exception.
Is there support for two-way binding?
|
|
|
|

|
Hey myker!
Can you send me the sample app via email so I can have a look?
|
|
|
|

|
Hey,
I invesstigated a little bit about the WPF-Toolkit Datagrid. I found this link:
http://forum.invist.net/showthread.php?p=1854[^]
It seems that the Edit-In-Place functionslities are only available if you bind to a List. The ObjectLounge collections implement IList, which seems not to be enough (but should be enough). In addition, it seems strange that if you bind to a simple IEnumerable, the grid won't even allow you the Edit functionality (edit is not add). You could wrap the Context-Collections in a List property of your ViewModel / CodeBehind. That seemed to work.
What I can tell you about the ObjectLounge collections is: Writable collections implement INotifyCollectionChanged and IList, so binding is possible, and we do that with "normal" WPF components.
Right now, we are developing a CRUD tool that is highly configurable. When it's ready, we will post it.
Cheers!
|
|
|
|

|
Nice Article!! (I sense some DB4O inspitation)
Just one philosophical issue: The problem with this kind of approach is that you always get a dirty model, because you always end with a decorated model. Is like using Castle's Active Record[^].
This [anti-?]pattern mixes 2 different layer of the application, the Domain Model and the Persistence. A mapping structure a la NHibernate (an XML file or any other form of defining the relation between the object and how is persisted) allows you to grab your model and use it in another development. It also keeps the separation of responsibilities.
Just that.
I'm on a Fuzzy State: Between 0 an 1
|
|
|
|

|
Thanks for your remarks. My view on the subject is the following (I am one of the co-developers of ObjectLounge).
You are right when you say that by adding attributes to your domain classes you might end up with a lot of them for different purposes (persistence, validation, security etc.) but after all that's the idea behind metadata: If e.g. a property should be persisted and verified and security checked and... why not just say so at the point of definition of the property? If you rather split out this data in separate files, your domain model class stays smaller. On the other hand it becomes less evident which metadata belongs to it, because you have to find all metadata references to it in various files. This could be especially difficult if the metadata is expressed in XML (like Hibernate mappings) because there is no help via the .Net type system (think "Find all references" in Visual Studio).
A compromise might be to use attributes (for better correlation between metadata and code) but to include only a minimal set of data in them and refer to external configuration data if it grows to big sizes (to keep the domain class small).
In the end, the problem is rather nonexistent right now since the attributes are few and mostly without additional configuration data.
|
|
|
|

|
Can I use this in a multiuser environment?
If yes, How can I handle concurrency? How many users it will support?
How can I ensure that one property value is unique?
Can I use this with a big size File?
What you could say about its performance?
|
|
|
|

|
Hi Georani,
very good questions. On my homepage, there are maybe some short answers, too.
1) Can I use this in a multiuser environment?
Yes. It's possible to have multiple transactions running. Transactions are thread-bound, means: One transaction per accessing thread.
Reading: "Read-Committed" Stategy, means: Every transaction has it's own isolated state, so you read only the committed data OR the data you changes inside "your" transaction.
As soon as you try to write properties, the framework automatically queues the write requests.
2) How can I ensure that one property value is unique?
Constraints like these (or other constraints) are managed by validation rules. I did not yet explain validation, but I will post an article as soon as possible. Short example:
public class Author : INotifyPropertyChanged
{
...
[ApplicationContext]
public virtual DomainModelContext Context { get; set; }
[ValidationRule]
protected ValidationResult ValidateNameUnique()
{
if (Context.Authors != null)
{
var notUnique = Context.Authors
.Where(it => it != this)
.Any(it => it.Name == this.Name);
if (notUnique)
return ValidationResult.Failure("The Name must be unique.");
else
return ValidationResult.Success();
}
else
return ValidationResult.Success();
}
...
}
You see here that you can access your domain model context by creating a property and decorating it with the <code>ApplicationContext</code> attribute. The validation method is automatically invoked when a transaction is committed. If a rule fails, a <code>ValidationException</code> is thrown that you have to catch. In this way, you can model any constraint you want. In the future, we plan to have built-in constraints that you can just put above your properties for the most common things.
3) Can I use this with a big size File? / What you could say about its performance?
We have some applications already running in production environments, but an older version of ObjectLounge. There, performance is good, because we don't have to fetch data all the time from the database, and we do mostly in-memory querying. But we have to run stress tests with this version, thus we changed a lot. If you would like to try out something, please let me know your experiences.
Cheers!
Ronald
modified on Monday, July 20, 2009 1:56 PM
|
|
|
|

|
Thank you.
More questions:
Can I use it in a shared folder like MS-Access, and many concurrent users?
Do you plan add server capability?
Is there any mechanism to ensure database integrity?
Is there any mechanism to repair a database?
|
|
|
|

|
- You cannot share the storags file. There can only be ony process accessing it.
- You can make your domain model accessible for other processes by wrapping it with a service layer (we use usually WCF).
- We plan to add server capability. This will be some kind of process that hosts the domain model and exposes automatically generated Get / Set methods via WCF.
- The Framework ensures referencial integrity of your domain model and ensures that all your validation constraints are fulfilled when you commit. In other words: If your domain model is in a consistent state before a transaction, it will be in a concistent state after a transaction.
- In which way should it be broken?
|
|
|
|

|
Thank you.
Ronald Schlenker wrote: In which way should it be broken?
When I tell about "database integrity" and "repair database", I was telling about file corrupting.
This can happens when hardware fails.
Example: MS-Access has an option "compact and repair database"
|
|
|
|

|
Ah, ok. Not I understand what you mean. The storage file created is a simple SQL-CE database (with only one table in which we dump the entity's XML). We don't use anything of the database functionality, no schema, no indexing, no constraints or relations, because all this is managed by the framework. What we needed was just a file based store.
So: You can use all the functionalitites that are provided by SQL-CE (maybe also repair if the file is corrupted).
|
|
|
|

|
Thank you.
Now I understand.
1- Do you have plans to use SQL Server Express instead of SQL-CE? If yes the database could be shared across many machines. If not, why?
2- Have you heard about http://persistor.net/[^]? It seems to be very similar to your project, but it is a very expensive product.
|
|
|
|

|
1) No plans richt now. If you would like to use ObjectLounge, we could write you one (it would be pretty similar to the SQL-CE provider we already have). But remember: There would just be one table (with one row per entity), in which we would dump the serialized XML. Technically, it would also be possible that the sync provider creates more complex schemata mapping the domain model to an ER model, but for us this would be too much work for now.
2) No, I didn't know that thing. But it's true, sounds pretty similar to what we have, also from the idea snd the philosophy behind it.
Cheers!
Ronald
|
|
|
|

|
Hi Ronald,
first of all your article is very interesting. I think you'll have my vote of 4...
I have just only a question: which are the supported databases and how to build up the connection string?
Thanks in advance
the CreF
the CreF
|
|
|
|

|
Hey, thanks CreF!
To give a short answer: There is no need for a database.
First of all, not to get me wrong: This framework is not an ORM. If you use the framework, you are actually developing a customized database, and there's usually no need to connect to a sql database or something. By default, you just have to provide a file name, and the framework creates a "store" for you in the filesystem (little bit like in db4o).
If that doesn't fit, you can implement what we call "SyncProvider". When the framework wants to persist entities, your implementation gets a changeset with inserted, deleted and updated entities. You can use and mapper or data access logic that is necessary to dump the entities in your prefered store (for example a relational database).
Hope I could help you!
Cheers
Ronald
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Host your Domain Models "Out Of The Box" + No storage or schema needed + Transactions on Domain Models + Validation
| Type | Article |
| Licence | LGPL3 |
| First Posted | 20 Jul 2009 |
| Views | 20,265 |
| Downloads | 264 |
| Bookmarked | 44 times |
|
|