TYPO3 9: Recursive count subpages of root page - typo3-9.x

is TYPO3 able to collect recursive and show the amount of subpages (no storages) from a specific root page? Tried this typoscript snippet but it is not working somehow.
20 = CONTENT
20 {
table = pages
select {
selectFields = count(*)
pidInList = <ROOT-PID>
andWhere = (hidden=0 AND deleted=0)
}
renderObj = COA
renderObj {
10 = TEXT
10 {
field = count(*)
wrap = Counted pages: |
}
}
}
Maybe there is some function in TYPO3 9?
Thanks in advance!

As the data is stored as a tree you need a recursion to get all pages from all sublevels.
As you can't know the depth (or expect a high number) and typoscript as a configuration language has no recursion build in a pure typoscript solution would be complicated.
Here a userfunc written in PHP and with recursion could be a quick solution.
In general:
Why do you need that number?
Maybe there is a simpler solution
here a pure typoscript solution you might start with:
for each menu-entry you get the sum of all pages up to three levels deeper and the count of pages on the next level.
temp.menudef = TMENU
temp.menudef {
#target = _top
noBlur = 1
#expAll = 1
wrap = <ol>|</ol>
NO = 1
NO {
stdWrap.cObject = COA
stdWrap.cObject {
1 = TEXT
1.field = title
1.required = 1
10 = LOAD_REGISTER
10.level1uids.cObject = COA
10.level1uids.cObject {
10 = CONTENT
10.table = pages
10.select.pidInList.data = field:uid
10.renderObj = TEXT
10.renderObj.field = uid
10.renderObj.wrap = |,
20 = TEXT
#20.field = uid
20.data = field:uid
}
10.level2uids.cObject < .10.level1uids.cObject
10.level2uids.cObject.10.select.pidInList.data = register:level1uids
10.level2uids.cObject.20.data = register:level1uids
10.level3uids.cObject < .10.level1uids.cObject
10.level3uids.cObject.10.select.pidInList.data = register:level2uids
10.level3uids.cObject.20.data = register:level2uids
20 = TEXT
20.wrap = <!-- --> (|
20.required = 1
20.override.numRows.table = pages
20.override.numRows.select.pidInList.data = register:level3uids
20.override.stdWrap.ifEmpty =
20.override.stdWrap.ifEmpty.wrap = |
30 = TEXT
30.wrap = -|)
30.required = 1
30.override.numRows.table = pages
30.override.numRows.select.pidInList.field = uid
30.override.stdWrap.ifEmpty =
30.override.stdWrap.ifEmpty.wrap = |
}
}
NO.wrapItemAndSub = <li>|</li>
NO.accessKey = 1
ACT < .NO
#ACT = 1
ACT.wrapItemAndSub = <li class="activ">|</li>
SPC < .NO
#SPC = 1
SPC.wrapItemAndSub = <li><span class="spacer">|</span></li>
CUR < .ACT
#CUR = 1
CUR.linkWrap = <span class="act">|</span>
CUR.wrapItemAndSub = <li class="current">|</li>
}
temp.submenu = HMENU
temp.submenu {
entryLevel = 0
wrap = <div class="smenu">|</div>
1 < temp.menudef
2 < .1
3 < .2
4 < .3
5 < .4
}

Related

Looping to a certain number based on some condition for a soap request

Scenario : send post request until a condition meet but maximum 5 times otherwise fail the script
step1: get one data from database
step2: get 2nd data from db based on step one result(if step 2 gives null then start again from step 1 and maximum occurrence can be 5 times)
step3: prepare a soap request and put 1st and 2nd data as input in the request body which we got in step 1 and 2.
Step4: send a soap request and print the response
step5: validate if response.id >5000(if this condition doesn't fulfill repeat the process from step1 to step 5 but again repeat only till 5 times and if still condition doesn't fulfill till 5th time then fail the test case)
Note:- I tried with retry until as well but looks like it keeps sending the step 5 only so it will not change the request body data which we need to change after every run from step 1 to step 5.
Also, I researched a lot and came across many similar questions but couldn't achieve my desired result.
Condition based on response value in karate
Scenario: GetCountriesWithId
* def RandomNumber =
"""
function() {
var count = 1
while (count<=5) {
var RandomNumber = db.readRows("select trunc(dbms_random.value(10000000, 10010000)) min, trunc(dbms_random.value(10200000, 10250000)) max from dual")
karate.log('RandomNumber->',RandomNumber)
var HolderFromDB = db.readRows("SELECT productId, userId from table1 WHERE id between "+RandomNumber[0].MIN+" and "+RandomNumber[0].MAX+" ")
if (HolderFromDB.length >= 1) {
karate.log('condition satisfied, exiting');
return HolderFromDB;
}
count++
}
}
"""
* def HolderFromDB = call RandomNumber
* def productId = HolderFromDB.productId
* def userId = HolderFromDB.userId
* def javaclass = Java.type('epos.positionmanagement.service.test.GetSpendingLimitRequestTest')
* def map = {deviceTypeId: 2, entityId: '#(defaultEntity)', ppr_id: '#(productId)', userId: '#(userId)' }
* def createGetSpendingLimitRequest = javaclass.getPayload(map)
Then print 'Request body--->', createGetSpendingLimitRequest
Given request createGetSpendingLimitRequest
When soap action 'Request'
Then status 500
Then print '\n', response
* def revisionId = get response //GetSpendingLimitResponse/spendingLimit/totalAmount*1
* def result = revisionId<=50000 ? karate.call('test1.feature') : {}
I think this test case should not be automated. Because it is not clear and it has a lot of dependent situation. You should take principle for making each test case standalone and independent. Also Test cases should have been good designed so that you can easily develop a code for them. Otherwise even if you have achieved to automate them, they will be most probably flaky tests and you will spend more time to fix them instead of testing them manually. Think twice, think scenarios once more also and decide your next move. Also please take a look this business logic which mentioned in your scenarios once more since it doesn't look so logical.
I have resolved the issue as below:-
Put the steps till post request in another feature file as below:-
#ignore
Feature: Reusable
Background: Maintenance Soap Request
* def DbUtils = Java.type('util.DbUtils')
* def db = new DbUtils(eposEnvironment.database[defaultEntity])
* url eposEnvironment.baseUrl
#Limit-GTC-Straddle #parallel=false
Scenario: Limit-GTC-Straddle
* def derivativeOrderTemp =
"""
function() {
var count = 1
while (count <= 10) {
var selectRandomLetter = db.readRows("select chr(trunc(dbms_random.value(65,74))) firstLetter, chr(trunc(dbms_random.value(80,90))) lastLetter, trunc(dbms_random.value(1, 4)) positionToBuy, to_char(current_date + 364, 'YYYY-MM-DD') expDate from dual")
var symbol1FromDB = db.readRows("select * from (select be_symbool, RTRIM(be_muntsoort) as be_muntsoort, be_code, be_optietype, be_expiratiedatum as be_expiratiedatum2, to_char(to_date(be_expiratiedatum, 'YYYYMMDD'), 'YYYY-MM-DD') as be_expiratiedatum, be_exerciseprijs, brs_naam, be_bv_beurs, round(max (quot_laat) keep (dense_rank last order by quot_datum)+ 1, 0) as limit, (round(max (quot_laat) keep (dense_rank last order by quot_datum)+ 1, 0)*100*-1*" + selectRandomLetter[0].POSITIONTOBUY + ") effAmount, be_volgnummer from beleggingsinstrument join fn_quotes_table on quot_symbool = be_symbool and quot_optietype = be_optietype and quot_expiratiedatum = be_expiratiedatum and quot_exerciseprijs = be_exerciseprijs join beurzen on brs_nummer = be_bv_beurs where be_Symbool in (select be_symbool from beleggingsinstrument where be_bi_nummer = 100 and length(trim(be_symbool)) < 4 and substr(trim(be_symbool),1,1) between '" + selectRandomLetter[0].FIRSTLETTER + "' and '" + selectRandomLetter[0].LASTLETTER + "' and be_geblokkeerd = 0 and be_handelen_toegestaan = 1 and be_referentiesymbool = ' ') and be_optietype = 'CALL' and be_handelen_toegestaan = 1 and be_expiratiedatum > to_char(sysdate, 'yyyymmdd') group by be_symbool, be_muntsoort, be_code, be_optietype, be_expiratiedatum, be_exerciseprijs, be_bv_beurs, quot_laat, brs_naam, quot_laat, quot_datum, be_volgnummer ) where rownum = 1")
karate.log('Symbol1FromDB-->', symbol1FromDB)
if (symbol1FromDB.length >= 1) {
karate.log('condition satisfied, exiting from first conditionalGoto1 loop counter');
var indirectCosts1FromDB = db.readRows("select icf_cfcu_id, cfcu_description, decode(icf_amount, null, 0, icf_amount) icf_amount, decode(icf_currency, null, 'NULL', icf_currency) icf_currency, decode(icf_percentage, null, 0, icf_percentage) icf_percentage from EPP_OWNER.INDIRECT_COSTS_PER_FUND join epp_owner.calculationrules on cfcu_id = icf_cfcu_id where icf_be_id = " + symbol1FromDB[0].BE_VOLGNUMMER + " and (icf_import_date_till > to_char(sysdate, 'yy-mm-dd') or icf_search_date_till is null) and icf_ex_ante_ex_post_ind = 'A' and icf_cfcu_id in (67)")
karate.log('indirectCosts1FromDB-->', indirectCosts1FromDB)
var symbol2FromDB = db.readRows("select * from (select be_symbool, RTRIM(be_muntsoort) as be_muntsoort, be_code, be_optietype, to_char(to_date(be_expiratiedatum, 'YYYYMMDD'), 'YYYY-MM-DD') as be_expiratiedatum, be_exerciseprijs, brs_naam, be_bv_beurs, round(max (quot_laat) keep (dense_rank last order by quot_datum)+ 1, 0) as limit, (round(max (quot_laat) keep (dense_rank last order by quot_datum)+ 1, 0)*100*-1*" + selectRandomLetter[0].POSITIONTOBUY + ") effAmount, be_volgnummer from beleggingsinstrument join fn_quotes_table on quot_symbool = be_symbool and quot_optietype = be_optietype and quot_expiratiedatum = be_expiratiedatum and quot_exerciseprijs = be_exerciseprijs join beurzen on brs_nummer = be_bv_beurs where be_Symbool = '" + symbol1FromDB[0].BE_SYMBOOL + "' and be_optietype = 'PUT' and be_handelen_toegestaan = 1 and be_expiratiedatum = '" + symbol1FromDB[0].BE_EXPIRATIEDATUM2 + "' group by be_symbool, be_muntsoort, be_code, be_optietype, be_expiratiedatum, be_exerciseprijs, be_bv_beurs, quot_laat, brs_naam, quot_laat, quot_datum, be_volgnummer ) where rownum = 1")
karate.log('Symbol2FromDB-->', symbol2FromDB)
var indirectCosts2FromDB = db.readRows("select icf_cfcu_id, cfcu_description, decode(icf_amount, null, 0, icf_amount) icf_amount, decode(icf_currency, null, 'NULL', icf_currency) icf_currency, decode(icf_percentage, null, 0, icf_percentage) icf_percentage from EPP_OWNER.INDIRECT_COSTS_PER_FUND join epp_owner.calculationrules on cfcu_id = icf_cfcu_id where icf_be_id = " + symbol2FromDB[0].BE_VOLGNUMMER + " and (icf_import_date_till > to_char(sysdate, 'yy-mm-dd') or icf_search_date_till is null) and icf_ex_ante_ex_post_ind = 'A' and icf_cfcu_id in (67)")
karate.log('indirectCosts2FromDB-->', indirectCosts2FromDB)
var selectRandomNumber = db.readRows("select trunc(dbms_random.value(10020000, 10050000)) min, trunc(dbms_random.value(11000000, 11500000)) max from dual")
karate.log('selectRandomNumber-->', selectRandomNumber)
var holderFromDB = db.readRows("SELECT * from (select ap_relatienr, ap_rekeningnr, hpp_holdernummer, ppr_id from aktuele_posities ap join epp_owner.rekeningen_per_product on rpp_relatienummer = ap.ap_relatienr and rpp_rekening_nummer = ap.ap_rekeningnr and rpp_rekeningsoort = ap.ap_rekening_soort join epp_owner.holders_per_product on hpp_relatienummer = rpp_relatienummer and hpp_product = rpp_productnummer and hpp_product_volgnr = rpp_volgnr_per_product and hpp_type_holder = 1 join rekeningen on re_rekening = rpp_rekening_nummer and re_nummer = rpp_relatienummer and re_rekening_status = 2 join epp_owner.wwwusers on wus_holder = hpp_holdernummer and wus_userblocked = 0 join producten_per_relatie on ppr_relatienummer = rpp_relatienummer and ppr_productnummer = rpp_productnummer and ppr_volgnr_per_product = rpp_volgnr_per_product JOIN on_line_dossier onld ON onld.onld_relatienummer = hpp_relatienummer and onld_productnummer = rpp_productnummer join kennis_per_client a on rpp_relatienummer = ke_clientnr where rpp_productnummer = 100 and rpp_volgnr_per_product = 1 and ap.ap_rekening_soort = 1000 and ap_saldo_positie > 7000 AND ap.ap_relatienr between " + selectRandomNumber[0].MIN + " and " + selectRandomNumber[0].MAX + " and onld.onld_klasse = 16 and onld.onld_ontvangstdatum <> '00000000' and onld.onld_vervaldatum = '00000000' and ((ke_kennis_niv = 'V' or ke_ervaring = 'V') and ke_mifcat_id = 25) and not exists (select 1 from kennis_per_client b where (ke_kennis_niv = 'O' or ke_ervaring = 'O') and a.ke_clientnr = b.ke_clientnr) and rpp_relatienummer in (select cl_nummer from clienten where cl_nummer between " + selectRandomNumber[0].MIN + " and " + selectRandomNumber[0].MAX + " and cl_geb_datum < to_char(add_months(sysdate, -216), 'YYYYMMDD')) and not exists (select 1 from profiel_toevoeging_verwijderen where ptv_relatie = ap.ap_relatienr) and not exists (select 1 from rekeninghouders_details where UPPER(eor_compliancecode) like 'INSIDER%' and eor_partij_id = hpp_holdernummer) ) where rownum = 1")
karate.log('holderFromDB-->', holderFromDB)
while (count <= 10) {
if (holderFromDB.length >= 1) {
karate.log('condition satisfied, exiting from conditionalGoto2');
productId = holderFromDB[0].get('PPR_ID')
userId = holderFromDB[0].get('HPP_HOLDERNUMMER')
return {
productId,
userId
};
}
count++;
if (count >= 9) {
karate.fail('Count exceeded more than 10 times and conditionalgoto2 loop counter failed')
}
}
count++;
if (count >= 9) {
karate.fail('Count exceeded more than 10 times and conditionalgoto1 loop counter failed')
}
}
}
}
"""
* def derivativeTemp = call derivativeOrderTemp
* def productId = derivativeTemp.productId
* print 'Product Id is-->',productId
* def userId = derivativeTemp.userId
* print 'User Id is-->',userId
################GetSpendingLimit###########################
* def javaclass = Java.type('epos.positionmanagement.service.test.GetSpendingLimitRequestTest')
* def map = {deviceTypeId: 2, entityId: '#(defaultEntity)', ppr_id: '#(productId)', userId: '#(userId)' }
* def createGetSpendingLimitRequest = javaclass.getPayload(map)
Then print 'Request body--->', createGetSpendingLimitRequest
Given request createGetSpendingLimitRequest
When soap action 'Request'
Then print '\n', response
And then call this feature file from other test case feature file as below :-
#Ordering
Feature: CreateCombinationDerivativeOrderTemp
Background: Ordering Soap Request
* url eposEnvironment.baseUrl
#parallel=true
Scenario: Limit-GTC-Straddle
* call read('reusable.feature#Limit-GTC-Straddle')
* def revisionId = get response //GetSpendingLimitResponse/spendingLimit/totalAmount*1
# * eval for(var i=0; i<=10; i++) (revisionId<3000 && i<10 ? karate.call('request1.feature') : karate.fail('Condition did not fulfill in 10 occurrence hence failing the test case'))
* def condionalgoto3 =
"""
function() {
for (var i = 0; i <= 10; i++) {
if (revisionId < 3000) {
karate.call('request1.feature')
if (i >= 9) {
karate.fail('Count exceeded more than 10 times and conditionalgoto3 loop counter failed')
}
}
}
}
"""
* call condionalgoto3
Note :- These java classes I am using to create a payload xml which was requirement of the project and these java classes are nothing but the actual services which I have added as pom dependency in my project which directly gives me the payload xml request and I just create a map and fill the value in the request body so these java classes are mandatory to use.And also these db queries are being used to fetch the actual customer details from a database to prepare the request body so there is nothing which I can ignore or improve in this test case but yes in some queries they are using some random values to fetch some customer data that I can definitely use some Java/Js/Karate.range() but apart from that I really dont think I can improve anything here.

Salesforce first error: INVALID_CROSS_REFERENCE_KEY, Entity not available

When I am trying to run my test class I am getting the below error.
System.DmlException: Update failed. First exception on row 0 with id 8023B000000ekyaQAA; first error: INVALID_CROSS_REFERENCE_KEY, Entity not available: [PricebookEntryId]
Also in the stack trace of debug log I am getting the below message
Class.OBOrderLineItemCreate.updateObjectMethod: line 367, column 1
I have Created the product and referenced the Standard price book. And have created the Pricebookentry, Order and Order line item. I am not sure why I am getting this error. Can anyone please help me with this and let me know what am I doing wrong? Thanks in advance.
My test class code is as below
Product2 prod = new Product2();
prod.Name = 'Inb Enterprise';
prod.Description = 'Annual subscription,80 topics, 40,000 company locations';
prod.productCode = 'ABC';
prod.Service_Type__c = 'Inb';
prod.OB_Sub_Type_Name__c = 'Inb';
prod.isActive = true;
insert prod;
Pricebook2 standardPricebook = new Pricebook2(
Id = Test.getStandardPricebookId(),
IsActive = true
);
update standardPricebook;
standardPricebook = [SELECT Id, IsStandard FROM Pricebook2 WHERE Id = :standardPricebook.Id];
//Id pricebookId = Test.getStandardPricebookId();
//Test.startTest();
PricebookEntry standardPrice = new PricebookEntry();
standardPrice.Pricebook2Id = standardPricebook.Id;
standardPrice.Product2Id = prod.Id;
standardPrice.UnitPrice = 10000;
standardPrice.IsActive = true;
insert standardPrice;
Order ord = new Order();
ord.Name = 'Test Order';
ord.AccountId = acc.Id;
ord.Pricebook2Id = standardPricebook.Id;
ord.Customer_Success_Manager__c = am.Id;
ord.Agency_Name__c = agc.Id;
ord.OpportunityId = opp.Id;
ord.Purchase_Order__c = '783983';
ord.EffectiveDate = Date.today();
ord.Status = 'Draft';
ord.OBSyncStatus__c = 'Inactive';
ord.End_Date__c = Date.today();
insert ord;
OrderItem oli = new OrderItem();
oli.OrderId = ord.Id;
oli.PricebookEntryId = standardPrice.Id;
oli.Quantity = 5;
oli.UnitPrice = 35;
oli.OBSyncStatus__c = 'Inactive';
oli.Line_Item_Start_Date__c = Date.Today();
oli.Line_Item_End_Date__c = Date.Today();
oli.Bonus_Units__c = 25;
oli.Geography__c = 'US';
oli.Unique_Line_Item_Name__c = 'Inb Order';
insert oli;
You don't need the code of instantiating the Pricebook2 object. Get rid of that code and use the code below.
standardPrice.Pricebook2Id = Test.getStandardPricebookId().
Do the same for ord.Pricebook2Id also.

Search bar in Selenium

I am unable to select an item if there is only 1 result showing(see image 1). If there are 2 results, desired item can be selected(see image 2). It just proceeds to the next scenario which inputs the date. it inputs the dates in the search bar instead of the date field. but works perfectly when there are 2 results.
Image 1
image 1
Image 2
image 2
Here is my code:
java.util.List<WebElement> substituterlist = getDriver.findElements(By.xpath("//*[#id='select2-drop']/ul/li"));
int list = substituterlist.size();
for (int i = 1; i <= list; i++) {
WebElement subUser = getDriver.findElement(By.xpath("//*[#id='select2-drop']/ul/li[" + i + "]/div"));
String subUsername = subUser.getText();
System.out.println(subUsername.indexOf("-"));
String selectUsr = subUsername.substring(0, subUsername.indexOf("-") - 1);
if (substituteUser.equals(selectUsr)) {
waitForMoreTime(10);
subUser.click();

Corona SQL pass row ID in tableView to new Scene

I've found a similair question to my problem and so far its working for me, Im getting the row ID printed with a print statement.
I am displaying data from my Database in a tableView. With the onTouch function I want the data showed in a new Scene in a scrollView that gets that data specifically to that clicked row. So for example I am clikcing on the tableView on Capital_NL, it has to show Amsterdam in the scrollView (Scene 2).
This is my code so far:
Scene 1:
local count = 0
local baslikRow = {}
for row in db:nrows("SELECT dua_id, baslik FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
end
local function tableViewListener( event )
print(event.phase)
end
local function onRowRender( event )
local row = event.row
local rowHeight = row.contentHeight
local rowWidth = row.contentWidth
local options =
{
parent = row,
text = baslikRow[row.index].baslik,
x = 20,
y = 0,
font = native.systemFont,
fontSize = 16
}
local rowTitle = display.newText(options)
rowTitle:setFillColor( 0, 0, 0 )
rowTitle.anchorX = 0
rowTitle.x = 15
rowTitle.y = rowHeight * 0.5
end
local function onRowTouch( event )
local row = event.row
if event.phase == 'tap' then
print("Pressed rowNR: " .. row.index )
print("Pressed rowID: " .. event.target.params.paramID)
composer.gotoScene("scene2")
end
end
local tableView = widget.newTableView{
left = 0,
top = 0,
height = display.contentHeight,
width = display.contentWidth,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
}
for i = 1, count do
tableView:insertRow
{
rowHeight = 50,
rowid = baslikRow[count].dua_id,
params = { paramID = baslikRow[i].dua_id }
}
end
sceneGroup:insert(tableView)
Scene 2:
---------------------
-- CREATE SCROLLVIEW
---------------------
local scrollView = widget.newScrollView
{
left = 0,
top = 0,
width = display.contentWidth,
height = display.contentHeight,
topPadding = 0,
bottomPadding = 0,
horiontalScrollDisabled = true,
verticalScrollDisable = false,
listener = scrollListener,
}
sceneGroup:insert(scrollView)
---------------------
-- GET DATA FROM DB
---------------------
for row in db:nrows("SELECT metni FROM dua") do
local rowParams =
{
duaID = row.dua_id,
Metni = row.metni,
}
local options =
{
text = row.metni,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 18,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
end
What I have right now is, whenever I click on, for example Capital_NL or Capital_USA or Capital_Germany, I always get the result Amsterdam back.
How do I pass the data thats in the same Row in the database from Scene 1 to Scene 2
I think you want to display the (metni) data based on the row number tapped on the previuos scene ..
Try this inside scene1 ..
for row in db:nrows("SELECT dua_id, baslik, metni FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
baslikRow[count].metni = row.metni
inside the onRowTouch event handler:
composer.gotoScene("scene2",{params = baslikRow[row.index].metni})
This way you can pass the data you want to use .. I guess you don't need to use the database code inside scene2 ..
to access the data passed from scene1 to scene2
local selectedRow = event.params
Then ..
local options =
{
text = selectedRow,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 50,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
I think thats what you asked for .. If NOT, please explain more and give us a screenshot of your "dua" table ..

Problem with Linq query .net MVC

public ActionResult Performances(string id)
{
var query =
from f in _db.Production
join g in _db.Run on f.show equals g.Production.show
join l in _db.Performance on g.startDate equals l.runStartDate
where f.show == id
select new ShowPerformance
{
Venuename = g.venue,
Showname = f.show,
RunStart = g.startDate,
RunEnd = g.endDate,
PerformanceDate = l.performanceDate,
PerformanceTime = l.performanceTime
};
return View(query.ToList());
}
The query can not distuingish between a performance in ShowA run1 and Show A run2 it just duplicates all performances ShowA run1 and Show A run2
I think the problem might be how you join Performance to Run/Production
var query =
from f in _db.Production
join g in _db.Run on new {f.show, f.year} equals new {g.show, g.year}
join l in _db.Performance on new {g.venue, g.startDate} equals new {l.venue, l.runStartDate}
where f.show == id
select new ShowPerformance
{
Venuename = g.venue,
Showname = f.show,
RunStart = g.startDate,
RunEnd = g.endDate,
PerformanceDate = l.performanceDate,
PerformanceTime = l.performanceTime
};
without something like the on g.runId equals l.runId then you will get all the performances for all the productions/runs.