Start MainDemo.Win.
Open the Department DetaiView.
Unlink all contacts.
Click Link - the displayed ListView does not contain unlinked contacts.
Click Save and Refresh, link a Contact to the Department.
Click Link - the linked Contact is still there.
Core - Linked objects are not removed from the link view immediately
Answers approved by DevExpress Support
We have fixed the issue described in this ticket and will include the fix in our next maintenance update. To apply this solution before the official update, request a hotfix by clicking the corresponding link for product versions you require.
Note: Hotfixes may be unavailable for beta versions and updates that are about to be released.
Hello,
We decided to change the default value for the LinkUnlinkController.ExcludeLinkedObjects property from true to false, which will fix this issue.
Our experience shows that implementing a universal solution for this task is not as easy as it appeared at the outset, because of a large number of possible scenarios.
For instance, our first implementation (SystemModules.Link - Exclude objects that are already linked to an object from the Link ListView) used the InOperator and it handled unsaved objects (InTransaction) very well. However, we observed that this InOperator-based implementation had two drawbacks:
- Linking a large number of objects at once (we first observed this while performing tests with our internal apps) may lead to reaching the parameter limit in a query for certain database servers (e.g., MS SQL Server, Oracle, etc.): http://stackoverflow.com/questions/845931/
This is further explained at Automatically split queries with In-Operator when too many operands are involved. - When a nested ListView is in server mode, this solution required loading all objects from the detail collection to work properly. We had no reports about this problem from our customers (quite likely because nested ListViews do not typically contain lots of records, so they rarely require server mode), but it might be a problem for them in the future.
So, we changed our initial implementation so as not to use the InOperator and to eliminate the aforementioned behaviors. However, it introduced the behavior described in this ticket.
While it seems that no generic solution combining only the advantages of the solutions I described exists for this particular scenario, it is still possible to filter out linked objects in your end application depending on the precise business scenario and requirements. It is possible because the LinkUnlinkController responsible for the linking operations provides plenty of events (SystemModules.Link - Provide events to create and customize a custom Link ListView) and virtual methods (e.g., CreateLinkView) to customize the default behavior.
For instance, you may find the following code helpful if you must filter out excluded objects if you are sure that you will not hit the database server limit on the number of parameters in a query:
C#using System.Collections;
using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.SystemModule;
public class MyLinkUnlinkController : LinkUnlinkController /*use WebLinkUnlinkController in ASP.NET*/ {
protected override void OnActivated() {
base.OnActivated();
ExcludeLinkedObjects = true;
}
protected override View CreateLinkView() {
ListView result = (ListView)base.CreateLinkView();
if (ExcludeLinkedObjects && View.CollectionSource.DataAccessMode == CollectionSourceDataAccessMode.Client && View.CollectionSource.List.Count > 0) {
ArrayList idList = new ArrayList(View.CollectionSource.List.Count);
foreach (object item in View.CollectionSource.List) {
idList.Add(ObjectSpace.GetKeyValue(item));
}
CriteriaOperator associatedCollectionCriteria = new InOperator(ObjectSpace.GetKeyPropertyName(View.ObjectTypeInfo.Type), idList);
result.CollectionSource.Criteria[CriteriaKeyForLinkView] = new NotOperator(associatedCollectionCriteria);
}
return result;
}
}
- v13.1.4Download Official Update
- v12.2.8Download Official Update
Does the suggested code still works in the current version (21.1.5)? I tried to implement it and had the following problem:
Lets say there is one object linked. I unlink it and then I link it again without committing in between. When the CreateLinkView method is called 'View.CollectionSource.List.Count' is always 0 and thus the object that was unlinked in the transaction is not displayed in the link view.
@Bernd, I tested this code in our demo with the latest version (v21.1.6) and it seems to work correctly. I cannot reproduce the issue you described. Please submit a new ticket and attach a small sample project that demonstrates the issue.