Updating an asset in Composer - hyperledger-composer

namespace com.biz
participant User identified by name {
o String name
}
participant Bank identified by name {
o String name
o Integer points
--> Document document optional
}
asset Document identified by docname {
o String docname
o String doctype
o String hash
o String from
o String to
}
transaction UploadDoc {
--> Document document
}
transaction ShareDoc {
--> Document document
--> Bank bank
}
transaction SetupDemo {
}
Script File :
/**
*
* #param {com.biz.UploadDoc} uploadDoc
* #transaction
*/
async function uploadDoc(uploadDoc) {
uploadDoc.document.docname = 'BC1.jpg';
uploadDoc.document.doctype = 'BC';
uploadDoc.document.hash = '123456';
uploadDoc.document.from = 'Bank_1';
uploadDoc.document.to = 'User_1';
const ar = await getAssetRegistry('com.biz.Document');
await ar.update(uploadDoc.document);
}
/**
*
* #param {com.biz.ShareDoc} shareDoc
* #transaction
*/
async function shareDoc(shareDoc) {
shareDoc.document.docname = 'BC1.jpg';
shareDoc.document.doctype = 'BC';
shareDoc.document.hash = '12346';
shareDoc.document.from = 'User_1';
shareDoc.document.to = shareDoc.bank.name;
const dr = await getAssetRegistry('com.biz.Document');
await dr.update(shareDoc.document);
}
/**
*
* #param {com.biz.SetupDemo} setupDemo
* #transaction
*/
async function setupDemo(setupDemo) {
const factory = getFactory();
const NS = 'com.biz';
const user = factory.newResource(NS,'User','User_1')
user.name='User_1';
const banks = [
factory.newResource(NS,'Bank','Bank_1'),
factory.newResource(NS,'Bank','Bank_2')
];
banks[0].name = 'Bank_1';
banks[1].name = 'Bank_2';
banks[0].points = 100;
banks[1].points = 100;
const userRegistry = await getParticipantRegistry(NS + '.User');
await userRegistry.addAll([user]);
const bankRegistry = await getParticipantRegistry(NS + '.Bank');
await bankRegistry.addAll(banks);
const documents = [
factory.newResource(NS, 'Document', 'Pa60.jpg'),
factory.newResource(NS, 'Document', 'Pa80.jpg')
];
documents[0].docname = 'Pa60.jpg';
documents[0].doctype = 'DrivingLicense';
documents[0].hash = '12345';
documents[0].from ='Bank_1';
documents[0].to = 'User_1';
documents[1].docname = 'Pa80.jpg';
documents[1].doctype = 'DrivingLicense';
documents[1].hash = '123456';
documents[1].from ='Bank_1';
documents[1].to = 'User_1';
const docRegistry = await getAssetRegistry(NS + '.Document')
await docRegistry.addAll(documents);
}
Issue : First I run transaction SetupDemo. Runs fine.
Next, I run transaction UploadDoc. Runs fine. Pa60.jpg is updated as BC1.jpg. ID given in Plyground for submitting transaction : Pa60.jpg
Next, I want to run ShareDoc transaction. If I give ID as BC1.jpg while submitting transaction, 'Object with id 'BC1.jpg' not found' error.
Please help me resolve the issue.

Related

How can I retrieve Id of inserted entity using Entity framework Core?

I have a concern since as I am new to using EntityFramework Core, that if I add an object, that I still do not have the id generated by the database, sending the object to it in the transaction, I would add it automatically, this is my code ,
public async Task<ServiceResult<Common.Entities.Company>> SaveCompany(Domain.Models.Company companyModel, Domain.Models.Administrator administratoModel)
{
ServiceResult<Common.Entities.Company> serviceResult = new ServiceResult<Common.Entities.Company>();
try
{
if (user == null && companyExistsRnc == false)
{
Common.Entities.Company myCompany = new Common.Entities.Company
{
CompanyId = companyModel.CompanyId, // The id has not been generated yet,
CompanyName = companyModel.CompanyName,
Rnc = companyModel.Rnc,
CountryId = companyModel.Country.CountryId,
Telephone = companyModel.Telephone,
PersonContact = companyModel.PersonContact,
Address = companyModel.Address,
PhotoPath = companyModel.PhotoPath,
IsActive = false,
};
await _companyRepository.SaveCompany(myCompany); // this is the method that I add the company object to the database and do the savechanges
Common.Entities.User myUser = new Common.Entities.User
{
FirstName = administratoModel.FirstName,
SecondName = administratoModel.SecondName,
FirstLastName = administratoModel.FirstLastName,
SecondLastName = administratoModel.SecondLastName,
GenderId = administratoModel.Gender.GenderId,
PhoneNumber = administratoModel.Telephone,
Email = administratoModel.Email,
UserName = administratoModel.Email,
IsActive = administratoModel.IsActive,
UserTypeId = (short)Common.Core.UserType.Administrator,
Company = myCompany, // here I send the my company object for when I do the savechanges, I think it will add it to me
};
await _userHelper.AddUserAsync(myUser, administratoModel.Password);
await _userHelper.AddUserToRoleAsync(myUser, Common.Core.UserType.Administrator.ToString());
Common.Entities.Administrator myAdministrator = new Common.Entities.Administrator
{
AdministratorId = administratoModel.AdministratorId,
FirstName = administratoModel.FirstName,
SecondName = administratoModel.SecondName,
FirstLastName = administratoModel.FirstLastName,
SecondLastName = administratoModel.SecondLastName,
GenderId = administratoModel.Gender.GenderId,
Email = administratoModel.Email,
Telephone = administratoModel.Telephone,
IsActive = true,
PhotoPath = administratoModel.PhotoPath,
UserTypeId = (short)Common.Core.UserType.Administrator,
Company = myCompany, // company object without the id
User = myUser, // user object without the id
};
await _administratorRepository.SaveAdministrator(myAdministrator);
serviceResult.Data = myCompany;
serviceResult.Message = "Compañia agregada!";
}
}
I am new to using entity framework core, and if in case I am wrong in what I am doing please indicate in which part I am doing it wrong, to correct, I await your comments and would appreciate the help,

VS Code APEX CLI test method debugging

I am using the attached test class which contains one method (testManualApprovalProcessManuallyApproved) to debug my code.
I have turned on/off the apex debugger then got the debug logs and run the replay debugger to check my code, I have put a lot of break points between the Test.startTest(); and test.stopTest(); in the code below however when I run my replay debugger and step into the Test.startTest(); the debugger jump all the break points and finish the whole unit test method.
Is there a way to debug line by line between Test.startTest(); and test.stopTest();
#isTest
public class PPAndLoanApprovalProcessTest_NEW {
/**
* #name setup
* #parm
* #desc test set up method
* #version 1.0
* #author : Someone
**/
#testsetup
private static void setUp() {
Test.startTest();
LogSeverityLevelValue__c logLevelSettings = TestDataFactorySFN.createLoggingLevel();
Database.upsert(logLevelSettings);
//Switch on the triggers
List<Trigger_Bypass__c> tSwitch = TestDataFactorySFN.createTriggerSwitch();
Database.insert(tSwitch);
List<Account> listAccBus = new List<Account>();
List<Account> listAccInd = new List<Account>();
Profile p= [SELECT Id From Profile WHERE Name='nTest' OR Name='nTest2' LIMIT 1];
User smevsde = [SELECT Id FROM user WHERE profileid = : p.Id and IsActive = true LIMIT 1];
system.debug('setup smevsde-->' + smevsde.Id);
//insert Product structure matrix
Product_StructureMatrix__c prdstm = new Product_StructureMatrix__c();
prdstm.Name='987654321';
prdstm.Product__c='Commercial (VR)';
prdstm.Product_Type__c='SME - Term loan';
prdstm.Product_Type_ID__c='123456789';
prdstm.Segment__c='SME';
insert prdstm;
Product_StructureMatrix__c prdstm2 = new Product_StructureMatrix__c();
prdstm2.Name='987654321';
prdstm2.Product__c='Commercial';
prdstm2.Product_Type__c='SME - Line of credit';
prdstm2.Product_Type_ID__c='123456789';
prdstm2.Segment__c='SME';
insert prdstm2;
system.runAs(smevsde){
//Create Business Accounts
listAccBus = SystemTestDataFactory.createTestAccounts(1);
//Create Opportunity from Business Account
/**Method Definition : SystemTestDataFactory.oppcreate(Account Id,Name,Stage,Loss Reason,Product Line, Product Type,
Product, Amount, Source, Type)
**/
Integer NoOfOpps = 0;
List<Opportunity> oppList = new List<Opportunity>();
oppList.add(SystemTestDataFactory.oppcreate(listAccBus[0].Id, 'TestOpportunity', 'Proposed',
'NBC – Risk','SME','SME - Term loan','Commercial (VR)',500.00,'Prospecting','Increase'));
oppList.add(SystemTestDataFactory.oppcreate(listAccBus[0].Id, 'TestOpportunity', 'Proposed',
'NBC – Risk','SME','SME - Line of credit','Commercial',500.00,'Prospecting','Increase'));
NoOfOpps=oppList.size();
if(!oppList.isEmpty()){
Database.insert(oppList);
}
//Create Disbusrement Forecast
List<Disbursement_Forecast__c> disbForecast = TestDataFactorySFN.createDisbursementForecast(1,oppList.get(0).Id);
List<Disbursement_Forecast__c> disbForecast2 = TestDataFactorySFN.createDisbursementForecast(1,oppList.get(1).Id);
//Create Product Package
List<LLC_BI__Product_Package__c> prodpackaglist = SystemTestDataFactory.createProdPkg(1);
Database.insert(prodpackaglist);
//Create Loan linked and link it to PP
StaticTriggerValues.isLoanUpdateFromUI = false;
List<LLC_BI__Loan__c> loanList = new List<LLC_BI__Loan__c>();
loanList = SystemTestDataFactory.createLoans(noOfOpps,prodpackaglist.get(0).Id,oppList,listAccBus.get(0).Id);
//Update the opportunities with created loans
for(integer i=0;i<noOfOpps;i++){
oppList.get(i).LLC_BI__Loan__c = loanList.get(i).Id;
}
if(!oppList.isEmpty()){
Database.update(oppList);
}
}
}
/**
*Method Name: testManualApprovalProcessManuallyApproved
*Description: This method will test approval process manually approved scenario.
**/
#isTest
private static void testManualApprovalProcessManuallyApproved(){
//Given
Profile p= [SELECT Id From Profile WHERE Name='nTest' OR Name='nTest2' LIMIT 1];
Profile p1= [SELECT Id From Profile WHERE Name='nTest3'];
User smevsde = [SELECT Id FROM user WHERE profileid = : p.Id and IsActive = true LIMIT 1];
system.debug('method smevsde-->' + smevsde.Id);
User credoff = [SELECT Id FROM user WHERE profileid = : p1.Id and IsActive = true LIMIT 1];
Id crdOffQId = [SELECT Id from Group where Name =: System.Label.SFN_Credit_Team_Queue and Type
=: System.Label.SFN_Queue limit 1][0].Id;
LLC_BI__Product_Package__c pplist = [SELECT Id,LLC_BI__Status__c, OwnerId, Assigned_to_Me__c FROM
LLC_BI__Product_Package__c LIMIT 1];
pplist.LLC_BI__Status__c = 'Open';
pplist.LLC_BI__Reviewable_Loan_Facilities_Count__c = 1;
ProductPackages.isFirstTime = true;
StaticTriggerValues.ppAfterUpdate = true;
Database.update(pplist);
List<LLC_BI__Loan__c> loansList = [SELECT Id, LLC_BI__Stage__c, LLC_BI__Status__c,LLC_BI__Is_Review_Ready__c, OwnerId, LLC_BI__Product_Package__c
FROM LLC_BI__Loan__c WHERE LLC_BI__Product_Package__c =: pplist.Id ];
for(Integer i=0;i<loansList.size();i++){
loansList.get(i).LLC_BI__Stage__c = 'Underwriting';
}
//Loans.isCalledFirstTime = true;
Database.update(loansList);
Test.startTest();
//Create an approval request
//When
System.runAs(smevsde){
Approval.ProcessSubmitRequest req1 = new Approval.ProcessSubmitRequest();
req1.setComments('Submitting request for approval.');
req1.setObjectId(pplist.Id);
StaticTriggerValues.ppAfterUpdate = true;
Approval.ProcessResult result = Approval.process(req1);
System.assert(result.isSuccess());
List<Id> newWorkItemIds = result.getNewWorkItemIds();
List<Id> newWorkItemIds2 = new List<Id>();
List<Id> newWorkItemIds3 = new List<Id>();
Approval.ProcessSubmitRequest req2 = new Approval.ProcessSubmitRequest();
Approval.ProcessSubmitRequest req21 = new Approval.ProcessSubmitRequest();
for(Integer i=0;i<1;i++){
req2.setComments('Submitting request for approval.');
req2.setObjectId(loansList[i].Id);
Loans.isCalledFirstTime = true;
Approval.ProcessResult result2 = Approval.process(req2);
System.assert(result2.isSuccess());
newWorkItemIds2 = result2.getNewWorkitemIds();
req21.setComments('Submitting request for approval.');
req21.setObjectId(loansList[i+1].Id);
Loans.isCalledFirstTime = true;
Approval.ProcessResult result21 = Approval.process(req21);
System.assert(result21.isSuccess());
newWorkItemIds3 = result21.getNewWorkitemIds();
}
system.debug('newWorkItemIds2-->' + newWorkItemIds2);
system.debug('newWorkItemIds3-->' + newWorkItemIds3);
System.debug('Loans stage after approval submit-->' + loansList.get(0).LLC_BI__Stage__c);
//System.debug('Loans stage after approval submit-->' + loansList.get(1).LLC_BI__Stage__c);
ProductPackages.isFirstTime = true;
system.debug('newWorkItemIds-->' + newWorkItemIds);
System.runAs(credoff){
system.debug('credoff user Id' + credoff.Id);
pplist.Assigned_to_Me__c = credoff.Id;
ppList.OwnerId = credoff.Id;
Database.update(pplist);
system.debug('Assigned owner PP--' + pplist.OwnerId);
system.debug('Assigned owner Loan--' + loansList.get(0).OwnerId);
system.debug('Assigned owner Loan--' + loansList.get(1).OwnerId);
Approval.ProcessWorkItemRequest req3 = new Approval.ProcessWorkItemRequest();
req3.setComments('Approving request.');
req3.setAction('Approve');
req3.setWorkItemId(newWorkItemIds.get(0));
system.debug('req3.setWorkItemId-->' + newWorkItemIds.get(0));
StaticTriggerValues.ppAfterUpdate = true;
Approval.ProcessResult result3 = Approval.process(req3);
System.assert(result3.isSuccess(), 'Result Status 3:'+result3.isSuccess());
system.debug('Result Status 3: ' + result3);
system.debug('newWorkItemIds2 size--' + newWorkItemIds2.size());
for(Integer i=0;i<newWorkItemIds2.size();i++){
Approval.ProcessWorkItemRequest req4 = new Approval.ProcessWorkItemRequest();
req4.setComments('Approving request.');
req4.setAction('Approve');
req4.setWorkItemId(newWorkItemIds2.get(i));
system.debug('req4.setWorkItemId-->' + newWorkItemIds2.get(i));
//Loans.isCalledFirstTime = true;
Approval.ProcessResult result4 = Approval.process(req4);
system.debug('result4-->' + result4);
System.assert(result4.isSuccess(), 'Result Status 4:'+result4.isSuccess());
}
for(Integer i=0;i<newWorkItemIds3.size();i++){
Approval.ProcessWorkItemRequest req5 = new Approval.ProcessWorkItemRequest();
req5.setComments('Approving request.');
req5.setAction('Approve');
req5.setWorkItemId(newWorkItemIds3.get(i));
system.debug('req5.setWorkItemId-->' + newWorkItemIds3.get(i));
//Loans.isCalledFirstTime = true;
Approval.ProcessResult result5 = Approval.process(req5);
system.debug('result4-->' + result5);
System.assert(result5.isSuccess(), 'Result Status 5:'+result5.isSuccess());
}
}
}
//Then
test.stopTest();
LLC_BI__Product_Package__c ppNewList = [SELECT Id, LLc_BI__Status__c, OwnerId FROM LLC_BI__Product_Package__c
LIMIT 1];
system.assertEquals('Manually Approved', ppNewList.LLC_BI__Status__c);
system.assertEquals(smevsde.Id, ppNewList.OwnerId);
List<LLC_BI__Loan__c> loanListNew = [SELECT Id, LLC_BI__Stage__c, OwnerId, LLC_BI__Product_Package__c
FROM LLC_BI__Loan__c WHERE LLC_BI__Product_Package__c =: ppNewList.Id LIMIT 100];
for(Integer i=0;i<loanListNew.size();i++){
system.assertEquals('Pre-Closing', loanListNew.get(i).LLC_BI__Stage__c);
system.assertEquals(smevsde.Id, loanListNew.get(i).OwnerId);
}
}

Response status code does not indicate success: '400' ('Bad request')

i want to POST data to API in my android xamarin app using refit i've tested the API at Postman and it's working fine but at android app i'm getting exception Bad request.
Here is my android code i added the interface and the model i don't know what is the problem .
public interface RequestAPI
{
[Post("/request")]
Task<create_request> submit([Body] create_request request);
}
requestAPI= RestService.For<RequestAPI>("http://courier-magconsulting.azurewebsites.net/api");
button.Click += async delegate
{
try
{
create_request request = new create_request();
request.PickUpPhone = "7664554";
request.DownPayment = 89;
request.DeliveryFees = 56.8;
request.Note = "i need a help!";
request.RequestID = 88; // replace the value yourself
request.DekiveryLocationLatitude = 2323;
request.DeliveryLocationLongitude = 232;
request.PickUpLocationLatitude = 898;
request.PickUpLocationLongitude = 1123;
BroadcastType type = new BroadcastType();
type.Name = "All";
type.ID = 60; // replace the value yourself
request.BroadcastType = type;
Cargosize size = new Cargosize();
size.Name = "Small";
size.ID = 1; // replace the value yourself
request.Cargosize = size;
Cargoweight weight = new Cargoweight();
weight.Name = "Large";
weight.ID = 2; // replace the value yourself
request.CargoWeight = weight;
Sender sender_ = new Sender();
sender_.Name = "Ahmad";
sender_.SenderID = 1; // replace the value yourself
sender_.Phone = "8788";
sender_.SocialID = "8787";
sender_.RatingAvg = 5;
SenderStatus status = new SenderStatus();
status.ID = 1;
status.Name = "Active";
sender_.Senderstatus = status;
request.Sender = sender_;
create_request result = await requestAPI.submit(request);
Toast.MakeText(this, "Request created", ToastLength.Long).Show();
}
catch(Exception ex)
{
Toast.MakeText(this, ex.Message, ToastLength.Long).Show();
}
};

Creating new participant and adding array of assets by reference to it

I have a problem when trying to add a new asset to an array of assets which are part of the participant as a reference.
Here I have SharedAccount participant controlled by its members who are connected via their share in the account.
I want to write a transaction for creating a new SharedAccount by one person. When a person submits a transaction, it should create a share asset if that person and add it to SharedAccount's shares array.
Here's how my code looks like
.cto:
...
participant SharedAccount identified by sharedAccountId {
o String sharedAccountId
--> Share[] shares
o Double balance
o Double originalBalance
}
asset Share identified by shareId {
o String shareId
--> Person shareHolder
o Double amount
}
transaction CreateSharedAccount {
--> Person creator
o String accountName
o Integer amount
}
...
.js:
...
/**
* #param {org.mistral.bulliongrower.CreateSharedAccount} createSharedAccount
* #transaction
*/
async function CreateSharedAccount(createSharedAccount) {
const factory = getFactory();
const NS = 'org.mistral.bulliongrower';
// create share
const share = factory.newResource(NS, 'Share', createSharedAccount.creator.personId + 'SHARE');
share.amount = createSharedAccount.amount;
share.shareHolder = createSharedAccount.creator;
share.shareHolder.balance -= createSharedAccount.amount;
const sharesRegistry = await getAssetRegistry(NS + '.Share');
await sharesRegistry.add(share);
const personRegistry = await getParticipantRegistry(NS + '.Person');
await personRegistry.update(share.shareHolder);
// create sharedAccount
const sharedAcc = factory.newResource(NS, 'SharedAccount', createSharedAccount.accountName);
sharedAcc.shares.push(share);
sharedAcc.balance = createSharedAccount.amount;
sharedAcc.originalBalance = createSharedAccount.amount;
const sharedAccRegistry = await getAssetRegistry(NS + '.SharedAccount');
await sharedAccRegistry.add(sharedAcc);
}
...
I'm not sure if I should use factory.newRelationship and how, when adding a share Asset to SharedAccount.
The error I get in the playground when trying to execute the transaction is
TypeError: Cannot read property 'push' of undefined
try to do this:
/**
* #param {org.mistral.bulliongrower.CreateSharedAccount} createSharedAccount
* #transaction
*/
async function CreateSharedAccount(createSharedAccount) {
const factory = getFactory();
const NS = 'org.mistral.bulliongrower';
// create share
const share = factory.newResource(NS, 'Share', createSharedAccount.creator.personId + 'SHARE');
//const share = factory.newRelationship(NS, 'Share', createSharedAccount.creator.personId + 'SHARE');
share.amount = createSharedAccount.amount;
//share.shareHolder = factory.newRelationship(NS, 'Share', createSharedAccount.creator.personId);
share.shareHolder = createSharedAccount.creator;
share.shareHolder.balance -= createSharedAccount.amount;
const sharesRegistry = await getAssetRegistry(NS + '.Share');
await sharesRegistry.add(share);
const personRegistry = await getParticipantRegistry(NS + '.Person');
await personRegistry.update(share.shareHolder);
// create sharedacc
const sharedAcc = factory.newResource(NS, 'SharedAccount', createSharedAccount.accountName);
//sharedAcc.shares = factory.newRelationship(NS, 'Share', createSharedAccount.creator.personId);
//sharedAcc.shares[0] = factory.newRelationship(NS, 'Share', share.shareId);
// define an array
let sharesArray = [];
sharesArray.push(share);
sharedAcc.shares = sharesArray;
sharedAcc.balance = createSharedAccount.amount;
sharedAcc.originalBalance = createSharedAccount.amount;
// use getParticipantRegistry not getAssetRegistry
const sharedAccRegistry = await getParticipantRegistry(NS + '.SharedAccount');
await sharedAccRegistry.add(sharedAcc);
}
your transaction code should be something like below - some of your references weren't right (take too long to point out all the changes, so you can refer below).
I added a test string (for 'Person') just to show what you would do (to have a reason to update that particular participant registry).
Seems to me that SharedAccount is an asset not a participant. And you would use the appropriate JS API to update that type of registry.
balance is not a field on Person (it is on SharedAccount), but your code was trying to refer to it.
I've left comments for 'alternative ways' for declarations and such like - just by way of info.
/**
* #param {org.mistral.bulliongrower.CreateSharedAccount} createSharedAccount
* #transaction
*/
async function CreateSharedAccount(createSharedAccount) {
const factory = getFactory();
const NS = 'org.example.trading';
// create share
const share = factory.newResource(NS, 'Share', createSharedAccount.creator.personId + 'SHARE');
share.amount = createSharedAccount.amount;
console.log("amount is " + share.amount);
share.shareHolder = createSharedAccount.creator;
// share.shareHolder.balance -= createSharedAccount.amount; // won't work - balance is a field on SharedAccount not Person - moved it below
const sharesRegistry = await getAssetRegistry(NS + '.Share');
await sharesRegistry.add(share);
share.shareHolder.newstr = "123"; // setting 'SOME' field (I added 'newstr' in my model, see below - so as to have a reason to update / give an example
const personRegistry = await getParticipantRegistry(NS + '.Person');
await personRegistry.update(share.shareHolder);
// create sharedAccount
const sharedAcc = factory.newResource(NS, 'SharedAccount', createSharedAccount.accountName);
//let idsArray = new Array(); // alternative, or use implicit below.
let idsArray = [] ;
let shareAssetRelationship = factory.newRelationship(NS, 'Share', share.getIdentifier());
idsArray.push(shareAssetRelationship); // only one element anyway
sharedAcc.shares = idsArray;
sharedAcc.balance = createSharedAccount.amount; // this is a new resource - so balance is eq to trxn amount ?
sharedAcc.originalBalance = createSharedAccount.amount; // original balance is nothing or 'balance' ?....anyway....
const sharedAccRegistry = await getAssetRegistry(NS + '.SharedAccount');
await sharedAccRegistry.add(sharedAcc);
}
The model I used is this:
participant Person identified by personId {
o String personId
o String newstr
}
asset SharedAccount identified by sharedAccountId {
o String sharedAccountId
--> Share[] shares
o Double balance
o Double originalBalance
}
asset Share identified by shareId {
o String shareId
--> Person shareHolder
o Double amount
}
transaction CreateSharedAccount {
--> Person creator
o String accountName
o Integer amount
}

Entity Framework cycle of data

I have an Account object, which has many Transactions related to it.
In one method, I get all transactions for a particular account.
var transactionlines = (from p in Context.account_transaction
.Include("account_transaction_line")
// .Include("Account")
.Include("account.z_account_type")
.Include("account.institution")
.Include("third_party")
.Include("third_party.z_third_party_type")
.Include("z_account_transaction_type")
.Include("account_transaction_line.transaction_sub_category")
.Include("account_transaction_line.transaction_sub_category.transaction_category")
.Include("z_account_transaction_entry_type")
.Include("account_transaction_line.cost_centre")
where p.account_id == accountId
&& p.deleted == null
select p).ToList();
This is meant to return me a list of transactions, with their related objects. I then pass each object to a Translator, which translates them into data transfer objects, which are then passed back to my main application.
public TransactionDto TranslateTransaction(account_transaction source)
{
LogUserActivity("in TranslateTransaction");
var result = new TransactionDto
{
Id = source.id,
Version = source.version,
AccountId = source.account_id,
// Account = TranslateAccount(source.account, false),
ThirdPartyId = source.third_party_id,
ThirdParty = TranslateThirdParty(source.third_party),
Amount = source.transaction_amount,
EntryTypeId = source.account_transaction_entry_type_id,
EntryType = new ReferenceItemDto
{
Id = source.account_transaction_entry_type_id,
Description = source.z_account_transaction_entry_type.description,
Deleted = source.z_account_transaction_entry_type.deleted != null
},
Notes = source.notes,
TransactionDate = source.transaction_date,
TransactionTypeId = source.account_transaction_type_id,
TransactionType = new ReferenceItemDto
{
Id = source.z_account_transaction_type.id,
Description = source.z_account_transaction_type.description,
Deleted = source.z_account_transaction_type.deleted != null
}
};
... return my object
}
The problem is:
An account has Transactions, and a Transaction therefore belongs to an Account. It seems my translators are being called way too much, and reloading a lot of data because of this.
When I load my transaction object, it's 'account' property has a'transactions' propery, which has a list of all the transactions associated to that account. Each transaction then has an account property... and those account peroprties again, have a list of all the transactions... and on and on it goes.
Is there a way I can limit the loading to one level or something?
I have this set:
Context.Configuration.LazyLoadingEnabled = false;
I was hoping my 'Includes' would be all that is loaded... Don't load 'un-included' related data?
As requested, here is my TranslateAccount method:
public AccountDto TranslateAccount(account p, bool includeCardsInterestRateDataAndBalance)
{
LogUserActivity("in TranslateAccount");
if (p == null)
return null;
var result =
new AccountDto
{
Id = p.id,
Description = p.description,
PortfolioId = p.institution.account_portfolio_id,
AccountNumber = p.account_number,
Institution = TranslateInstitution(p.institution),
AccountType = new ReferenceItemDto
{
Id = p.account_type_id,
Description = p.z_account_type.description
},
AccountTypeId = p.account_type_id,
InstitutionId = p.institution_id,
MinimumBalance = p.min_balance,
OpeningBalance = p.opening_balance,
OpeningDate = p.opening_date
};
if (includeCardsInterestRateDataAndBalance)
{
// Add the assigned cards collection
foreach (var card in p.account_card)
{
result.Cards.Add(new AccountCardDto
{
Id = card.id,
AccountId = card.account_id,
Active = card.active,
CardHolderName = card.card_holder_name,
CardNumber = card.card_number,
ExpiryDate = card.expiry
});
}
// Populate the current interest rate
result.CurrentRate = GetCurrentInterestRate(result.Id);
// Add all rates to the account
foreach (var rate in p.account_rate)
{
result.Rates.Add(
new AccountRateDto
{
Id = rate.id,
Description = rate.description,
Deleted = rate.deleted != null,
AccountId = rate.account_id,
EndDate = rate.end_date,
Rate = rate.rate,
StartDate = rate.start_date
});
}
result.CurrentBalance = CurrentBalance(result.Id);
}
LogUserActivity("out TranslateAccount");
return result;
}
The entity framework context maintains a cache of data that has been pulled out of the database. Regardless of lazy loading being enabled/disabled, you can call Transaction.Account.Transactions[0].Account.Transactions[0]... as much as you want without loading anything else from the database.
The problem is not in the cyclical nature of entity framework objects - it is somewhere in the logic of your translation objects.

Resources