fix(transport): skip unbound (empty ConnectionName) bindings on import instead of writing FK=0 (M8 INT review)
This commit is contained in:
@@ -3237,25 +3237,28 @@ public sealed class BundleImporter : IBundleImporter
|
|||||||
}
|
}
|
||||||
foreach (var b in dto.ConnectionBindings)
|
foreach (var b in dto.ConnectionBindings)
|
||||||
{
|
{
|
||||||
|
// A binding may carry NO connection name — an unbound attribute, or a
|
||||||
|
// binding whose source connection was not included in the export. There
|
||||||
|
// is no meaningful target FK to write (DataConnectionId = 0 would be an
|
||||||
|
// invalid FK and FK-violate at commit on a relational provider), so skip
|
||||||
|
// the binding row entirely rather than persist a broken binding.
|
||||||
|
if (string.IsNullOrEmpty(b.ConnectionName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Resolve ConnectionName → target DataConnectionId. After the C1 Pass-2
|
// Resolve ConnectionName → target DataConnectionId. After the C1 Pass-2
|
||||||
// in ApplyDataConnectionsAsync, the map carries an entry for every
|
// in ApplyDataConnectionsAsync, the map carries an entry for every
|
||||||
// referenced connection — carried in the bundle OR auto-matched in the
|
// referenced connection — carried in the bundle OR auto-matched in the
|
||||||
// target. A binding whose connection name STILL doesn't resolve is a
|
// target. A non-empty name that STILL doesn't resolve is a structural
|
||||||
// structural error (it should already have been a preview blocker +
|
// error (it should already have been a preview blocker + a pre-write
|
||||||
// a pre-write validation failure); THROW rather than write
|
// validation failure); THROW rather than write an invalid FK.
|
||||||
// DataConnectionId = 0, which would be an invalid FK on a relational
|
if (!connectionMaps.IdBySourceRef.TryGetValue((sourceSiteIdentifier, b.ConnectionName), out var connId))
|
||||||
// provider and a silently-broken binding on the in-memory one.
|
|
||||||
// A binding may legitimately carry NO connection name (unbound
|
|
||||||
// attribute) — only a NON-EMPTY name that fails to resolve is an error.
|
|
||||||
if (!string.IsNullOrEmpty(b.ConnectionName)
|
|
||||||
&& !connectionMaps.IdBySourceRef.TryGetValue((sourceSiteIdentifier, b.ConnectionName), out _))
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
$"Instance '{inst.UniqueName}' binding for attribute '{b.AttributeName}' references "
|
$"Instance '{inst.UniqueName}' binding for attribute '{b.AttributeName}' references "
|
||||||
+ $"connection '{sourceSiteIdentifier}/{b.ConnectionName}' which could not be resolved "
|
+ $"connection '{sourceSiteIdentifier}/{b.ConnectionName}' which could not be resolved "
|
||||||
+ "to a target connection (present in neither bundle nor target).");
|
+ "to a target connection (present in neither bundle nor target).");
|
||||||
}
|
}
|
||||||
connectionMaps.IdBySourceRef.TryGetValue((sourceSiteIdentifier, b.ConnectionName), out var connId);
|
|
||||||
inst.ConnectionBindings.Add(new InstanceConnectionBinding(b.AttributeName)
|
inst.ConnectionBindings.Add(new InstanceConnectionBinding(b.AttributeName)
|
||||||
{
|
{
|
||||||
DataConnectionId = connId,
|
DataConnectionId = connId,
|
||||||
|
|||||||
Reference in New Issue
Block a user