You are not logged in.
Oops, that should be Suppliers.
Hi Ab,
When the function call ends, I get an access violation in ObjArrayClear(Value^) (mORMot.pas[48685]) from what I traced it looks like it's part of the cleanup after the call was dispatched.
Perhaps I'm not initializing the Array correctly?
function TSupplierQuery.GetSuppliers(const aCompanyID: RawUTF8; out Suppliers: TSupplierObjArray): TCQRSResult;
var
Res : ISQLDBRows;
Supplier : TSupplier;
I : integer;
begin
Result := cqrsNotFound;
Res := fDbConnection.Execute( 'select count(*) from SUPPLIERS where COMPANY_ID=?', [aCompanyID] );
if Res.Step then begin
ObjArraySetLength( Stores, 0 ); //Res.ColumnInt(0) ); -- Ideally I'd like to pre-allocate the array
Res := fDbConnection.Execute( 'select SUPPLIER_ID from SUPPLIERS where COMPANY_ID=?', [aCompanyID] );
while Res.Step do begin
Supplier := TSupplier.Create;
GetSupplier(Res['SUPPLIER_ID'], Supplier);
ObjArrayAdd( Suppliers, Supplier );
end;
end;
end;Just an update:
1. Declaring TSuppliers as a descendant of TCollection works, but then I can't use TSupplier on it's own.
2. Declaring TSuppliers as a TObjectList serializes the array properly, but adds the ugly ClassName property.
Hi Ab,
As my adventures in mORMot continues, I now sit with an interesting issue. This is probably a FAQ, but given the following:
type
TSupplier = class(TSynPersistent)
private
fName : RawUTF8;
published
property Name : RawUTF8 read fName write fName;
end;
TSuppliers = array of TSupplier;
ISuppliers = interface(IInvokable)
['{2BDC9F78-B9C2-4621-A557-F87F02AC0581}']
function GetSuppliers(const aLocationID: RawUTF8; out Suppliers: TSuppliers): TCQRSResult;
end;When invoking the interface, Suppliers are serialized as an array of integer?
Changing
TSuppliers = TObjectList<TSupplier>;Generates Access Violations.
I've also tried to call:
TJSONSerializer.RegisterObjArrayForJSON( TypeInfo(TStores), TStore);Which generates an error claiming that I have to write a custom serializer for TStore.
Some direction will be appreciated. ![]()
Darn it. I skim read it, and it seemed appropriate.
Thanks Ab.
Just a question on reentrancy:
Would my method above survive two simultaneous requests in sicShared mode? Id not, what do I have to do to protect it?
On that note, if my implementation is a bit more complex, how do I insure that my transaction doesn't get nabbed by some other request? (Since a single fDbConnection is shared among several possible requests.)
....
If you want to have arguments to your board, take a look at https://www.openhub.net/p/mormot
The https://www.openhub.net/p/mormot/estimated_cost page is easy to understand: if you use mORMot, you are very likely to invest of a huge proven code base, so would have immediate ROI!
If you can see in mORMot the tools you need, using it may help saving $3,789,656 in respect to an in-house solution.
...
Thanks Ab, all good points!
If you want something to support Delphi in general this review could be useful: ...
Excellent! A good read, thanks esmondb.
I'm having a similar problem. Our legacy database also uses varchar for primary keys, so no ORM.
I've defined DTO's (inherited from TSynPersistent) and CQRS interfaces to operate on these DTO's.
So basically I have this:
ILegacyStockQuery = interface(IInvokable)
['{2BDC9F78-B9C2-4621-A557-F87F02AC0581}']
function GetSupplier(const aID: TRevelightID; out Supplier: TLegacySupplier): TCQRSResult;
end;
TLegacyStockQuery = class(TInterfacedObject, ILegacyStockQuery)
public
constructor Create( aDbConnection : TSQLDBConnectionProperties );
function GetSupplier(const aID: TRevelightID; out Supplier: TLegacySupplier): TCQRSResult;
end;function TLegacyStockQuery.GetSupplier(const aID: TRevelightID; out Supplier: TLegacySupplier): TCQRSResult;
var
Res : ISQLDBRows;
begin
Result := cqrsNotFound;
Res := fDbConnection.Execute( 'select SUPPLIER_ID, SUPPLIER_NAME from SUPPLIERS where SUPPLIER_ID=? ', [aID] );
if Res.Step then begin
Result := cqrsSuccess;
Supplier.RevelightID := Res['SUPPLIER_ID'];
Supplier.Name := Res['SUPPLIER_NAME'];
end;
end;The issue I'm having is this: How do I get hold of the fDbConnection (TSQLDBConnectionProperties). I'd prefer to specify it when I create the specific server/service, and not to access a global or singleton.
Okay, thanks.
Hi Ab,
Going through your updated documentation on DDD and implementing CQRS, I'm curios why you implemented your IDomUserQuery they way you did.
Wouldn't it be easier/simpler to have:
IDomUserQuery = interface(ICQRSService)
['{198C01D6-5189-4B74-AAF4-C322237D7D53}']
function SelectByLogonName(const aLogonName: RawUTF8; out aAggregate: TUser): TCQRSResult;
function SelectByEmailValidation(aValidationState: TDomUserEmailValidation; out aAggregate: TUser): TCQRSResult;
function SelectByLastName(const aName: TLastName; aStartWith: boolean; out aAggregates: TUserObjArray): TCQRSResult;
function GetAll(out aAggregates: TUserObjArray): TCQRSResult;
function GetCount: integer;
function HowManyValidatedEmail: integer;
end;Thanks edwinsn.
I understand that, but was looking for some firepower to use in the boardroom. I'm specifically interested in large scale enterprise level projects.
Hi guys,
I know there's a thread dealing with this, but it only has 3 replies! Surely mORMot is used much more widely than that! You don't need to give details or specifications, we just want to get an idea of how widely mORMot is being used out there.
The CQRS stuff, seems great!
In terms of Event Source, I'm more concerned with assistance the ORM can provide in persisting the various events, snapshotting and providing general assistance managing the Event Log, as described here: https://github.com/eventstore/eventstor … ing-Basics
Hi Ab,
Event Sourcing has been on the road map for a while now. I'm wondering how mORMot can help in implementing these patterns at this stage?
Hi guys,
I might be wrong in my approach, but I would like to deal exclusively with interfaces when communicating between client and server. In my sandbox project I have a blog (for example). Let's call it IBlog and IBlog has a method:
IBlog = interface(IInvokable)
['{F4479253-C592-48D3-9658-FFE3C9EE07DE}']
function getName: string;
procedure setName(const Value: string);
function getPosts( out Posts : IPosts ) : integer;
end;
TBlog = class(TSQLRecordInterfaced, IBlog)
private
function getName: string;
procedure setName(const Value: string);
public
function getPosts( out Posts : IPosts ) : integer;
publsihed
property Name: string read getName write setName;
end;What should IPosts' definition look like?
I've been toying around with IEnumerator, IList and a couple of other friends, but none of these seem to really work well.
Hi Ab,
Thanks for your prompt reply. 20 - DTO interface based service was the sample that I was missing. It makes a lot more sense now.
Hi Ab,
I have been looking at mORMot for a bit, studied the SAD document and looked at the Code Samples, and I have some code structure questions:
1. I get the TSQLRecord is effectively your storage layer, so my business objects should be using TSQLRecord descendants to manipulate and query persistent objects, correct? What is the mechanism then, to use the same Business Object Model on both Client and Server, as implemented in mORMot?
2. How transparent can one make this to be able to scale from single to n-tiers, with no code changes?
3. Even though you discuss it in the SAD I do not see any implementation of dependence injection in the framework. Is this by design?
I am missing a sample to show how to properly structure a potentially huge project.
Kind regards,
Willo vd Merwe