Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntityDesign / Design / System / Data / Entity / Design / Common / OneToOneMappingSerializer.cs / 1 / OneToOneMappingSerializer.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Mapping;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Diagnostics;
using System.Xml;
using System.Data.Common.Utils;
using System.Linq;
namespace System.Data.Entity.Design.Common
{
internal static class OneToOneMappingSerializer
{
internal class MappingLookups
{
internal Dictionary StoreEntityTypeToModelEntityType = new Dictionary();
internal Dictionary StoreEdmPropertyToModelEdmProperty = new Dictionary();
internal Dictionary StoreEntitySetToModelEntitySet = new Dictionary();
internal Dictionary StoreAssociationTypeToModelAssociationType = new Dictionary();
internal Dictionary StoreAssociationEndMemberToModelAssociationEndMember = new Dictionary();
internal Dictionary StoreAssociationSetToModelAssociationSet = new Dictionary();
internal Dictionary StoreAssociationSetEndToModelAssociationSetEnd = new Dictionary();
internal List CollapsedEntityAssociationSets = new List();
}
// this class represents a construct found in the ssdl where a link table
// contained no data (all its properties were part of its keys)
// it has exactly two associations
// the entity type is the TO side of both associations
// all the colums are used as TO columns in the constraint
internal class CollapsedEntityAssociationSet
{
private EntitySet _storeEntitySet;
private List _storeAssociationSets = new List(2);
private AssociationSet _modelAssociationSet;
public AssociationSet ModelAssociationSet
{
get { return _modelAssociationSet; }
set
{
Debug.Assert(_modelAssociationSet == null, "why is this getting set multiple times, it should only be set after the new set is created");
_modelAssociationSet = value;
}
}
public CollapsedEntityAssociationSet(EntitySet entitySet)
{
Debug.Assert(entitySet != null, "entitySet parameter is null");
_storeEntitySet = entitySet;
}
public EntitySet EntitySet
{
get { return _storeEntitySet; }
}
public List AssociationSets
{
get { return _storeAssociationSets; }
}
public void GetStoreAssociationSetEnd(int index, out AssociationSetEnd storeAssociationSetEnd, out RelationshipMultiplicity multiplicity, out OperationAction deleteBehavior)
{
Debug.Assert(index >= 0 && index < AssociationSets.Count, "out of bounds dude!!");
Debug.Assert(AssociationSets.Count == 2, "This code depends on only having exactly two AssociationSets");
GetFromAssociationSetEnd(AssociationSets[index], AssociationSets[(index+1)%2], out storeAssociationSetEnd, out multiplicity, out deleteBehavior);
}
private void GetFromAssociationSetEnd(AssociationSet definingSet, AssociationSet multiplicitySet, out AssociationSetEnd associationSetEnd, out RelationshipMultiplicity multiplicity, out OperationAction deleteBehavior)
{
// for a situation like this (CD is CascadeDelete)
//
// -------- CD -------- CD --------
// | A |1 <- 1| AtoB |* <- 1| B |
// | |-------| |-------| |
// | | | | | |
// -------- -------- --------
//
// You get
// -------- CD --------
// | A |* <- 1| B |
// | |-------| |
// | | | |
// -------- --------
//
// Notice that the of the new "link table association" muliplicities are opposite of what comming into the original link table
// this seems counter intuitive at first, but makes sense when you think all the way through it
//
// CascadeDelete Behavior (we can assume the runtime will always delete cascade
// to the link table from the outside tables (it actually doesn't, but that is a bug))
// Store Effective
// A -> AToB <- B None
// A <- AToB <- B <-
// A -> AToB -> B ->
// A <- AToB -> B None
// A <- AToB B <-
// A AToB -> B ->
// A -> AToB B None
// A AToB <- B None
//
// Other CascadeDelete rules
// 1. Can't have a delete from a Many multiplicity end
// 2. Can't have a delete on both ends
//
associationSetEnd = GetAssociationSetEnd(definingSet, true);
AssociationSetEnd multiplicityAssociationSetEnd = GetAssociationSetEnd(multiplicitySet, false);
multiplicity = multiplicityAssociationSetEnd.CorrespondingAssociationEndMember.RelationshipMultiplicity;
deleteBehavior = OperationAction.None;
if (multiplicity != RelationshipMultiplicity.Many)
{
OperationAction otherEndBehavior = GetAssociationSetEnd(definingSet, false).CorrespondingAssociationEndMember.DeleteBehavior;
if(otherEndBehavior == OperationAction.None)
{
// Since the other end does not have an operation
// that means that only one end could possibly have an operation, that is good
// so set it the operation
deleteBehavior = multiplicityAssociationSetEnd.CorrespondingAssociationEndMember.DeleteBehavior;
}
}
}
private static AssociationSetEnd GetAssociationSetEnd(AssociationSet set, bool fromEnd)
{
Debug.Assert(set.ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[0]");
ReferentialConstraint constraint = set.ElementType.ReferentialConstraints[0];
Debug.Assert(set.AssociationSetEnds.Count == 2, "Associations are assumed to have two ends");
int toEndIndex, fromEndIndex;
if (set.AssociationSetEnds[0].CorrespondingAssociationEndMember == constraint.FromRole)
{
fromEndIndex = 0;
toEndIndex = 1;
}
else
{
fromEndIndex = 1;
toEndIndex = 0;
}
if (fromEnd)
{
return set.AssociationSetEnds[fromEndIndex];
}
else
{
return set.AssociationSetEnds[toEndIndex];
}
}
public bool MeetsRequirementsForCollapsableAssociation
{
get
{
if (_storeAssociationSets.Count != 2)
return false;
ReferentialConstraint constraint0;
ReferentialConstraint constraint1;
GetConstraints(out constraint0, out constraint1);
if (!IsEntityDependentSideOfBothAssociations(constraint0, constraint1))
return false;
if (!IsAtLeastOneColumnOfBothDependentRelationshipColumnSetsNonNullable(constraint0, constraint1))
return false;
if (!AreAllEntityColumnsMappedAsToColumns(constraint0, constraint1))
return false;
if (IsAtLeastOneColumnFKInBothAssociations(constraint0, constraint1))
return false;
return true;
}
}
private bool IsAtLeastOneColumnFKInBothAssociations(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return constraint1.ToProperties.Any(c => constraint0.ToProperties.Contains(c));
}
private bool IsAtLeastOneColumnOfBothDependentRelationshipColumnSetsNonNullable(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return ToPropertyHasNonNullableColumn(constraint0) && ToPropertyHasNonNullableColumn(constraint1);
}
private static bool ToPropertyHasNonNullableColumn(ReferentialConstraint constraint)
{
foreach (EdmProperty property in constraint.ToProperties)
{
if (!property.Nullable)
{
return true;
}
}
return false;
}
private bool AreAllEntityColumnsMappedAsToColumns(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
Set names = new Set();
AddToPropertyNames(constraint0, names);
AddToPropertyNames(constraint1, names);
return names.Count == _storeEntitySet.ElementType.Properties.Count;
}
private static void AddToPropertyNames(ReferentialConstraint constraint, Set names)
{
foreach (EdmProperty property in constraint.ToProperties)
{
names.Add(property.Name);
}
}
private bool IsEntityDependentSideOfBothAssociations(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return ((RefType)constraint0.ToRole.TypeUsage.EdmType).ElementType == _storeEntitySet.ElementType && ((RefType)constraint1.ToRole.TypeUsage.EdmType).ElementType == _storeEntitySet.ElementType;
}
private void GetConstraints(out ReferentialConstraint constraint0, out ReferentialConstraint constraint1)
{
Debug.Assert(_storeAssociationSets.Count == 2, "don't call this method if you don't have two associations");
Debug.Assert(_storeAssociationSets[0].ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[0]");
Debug.Assert(_storeAssociationSets[1].ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[1]");
constraint0 = _storeAssociationSets[0].ElementType.ReferentialConstraints[0];
constraint1 = _storeAssociationSets[1].ElementType.ReferentialConstraints[0];
}
}
public static void WriteXml(XmlWriter writer,
MappingLookups lookups,
EntityContainer storeContainer,
EntityContainer modelContainer)
{
EDesignUtil.CheckArgumentNull(writer, "writer");
EDesignUtil.CheckArgumentNull(storeContainer, "storeContainer");
EDesignUtil.CheckArgumentNull(modelContainer, "modelContainer");
WriteMappingStartElement(writer);
WriteEntityContainerMappingElement(writer, lookups, storeContainer, modelContainer );
writer.WriteEndElement();
}
private static void WriteEntityContainerMappingElement(XmlWriter writer, MappingLookups lookups, EntityContainer storeContainer, EntityContainer modelContainer)
{
writer.WriteStartElement(StorageMslConstructs.EntityContainerMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.StorageEntityContainerAttribute, storeContainer.Name);
writer.WriteAttributeString(StorageMslConstructs.CDMEntityContainerAttribute, modelContainer.Name);
foreach (EntitySet set in lookups.StoreEntitySetToModelEntitySet.Keys)
{
EntitySet modelEntitySet = lookups.StoreEntitySetToModelEntitySet[set];
WriteEntitySetMappingElement(writer, lookups, set, modelEntitySet);
}
foreach(AssociationSet set in lookups.StoreAssociationSetToModelAssociationSet.Keys)
{
AssociationSet modelAssociationSet = lookups.StoreAssociationSetToModelAssociationSet[set];
WriteAssociationSetMappingElement(writer, lookups, set, modelAssociationSet);
}
foreach (CollapsedEntityAssociationSet set in lookups.CollapsedEntityAssociationSets)
{
WriteAssociationSetMappingElement(writer, lookups, set);
}
writer.WriteEndElement();
}
private static void WriteAssociationSetMappingElement(XmlWriter writer, MappingLookups lookups, CollapsedEntityAssociationSet collapsedAssociationSet)
{
writer.WriteStartElement(StorageMslConstructs.AssociationSetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingNameAttribute, collapsedAssociationSet.ModelAssociationSet.Name);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingTypeNameAttribute, collapsedAssociationSet.ModelAssociationSet.ElementType.FullName);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingStoreEntitySetAttribute, collapsedAssociationSet.EntitySet.Name);
for (int i = 0; i < collapsedAssociationSet.AssociationSets.Count; i++)
{
AssociationSetEnd storeEnd;
RelationshipMultiplicity multiplicity;
OperationAction deleteBehavior;
collapsedAssociationSet.GetStoreAssociationSetEnd(i, out storeEnd, out multiplicity, out deleteBehavior);
AssociationSetEnd modelEnd = lookups.StoreAssociationSetEndToModelAssociationSetEnd[storeEnd];
WriteEndPropertyElement(writer, lookups, storeEnd, modelEnd);
}
// don't need condition element
writer.WriteEndElement();
}
private static void WriteAssociationSetMappingElement(XmlWriter writer, MappingLookups lookups, AssociationSet store, AssociationSet model)
{
writer.WriteStartElement(StorageMslConstructs.AssociationSetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingTypeNameAttribute, model.ElementType.FullName);
// all column names must be the primary key of the
// end, but as columns in the Fk table.
AssociationSetEnd foreignKeyTableEnd = GetAssociationSetEndForForeignKeyTable(store);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingStoreEntitySetAttribute, foreignKeyTableEnd.EntitySet.Name);
foreach (AssociationSetEnd storeEnd in store.AssociationSetEnds)
{
AssociationSetEnd modelEnd = lookups.StoreAssociationSetEndToModelAssociationSetEnd[storeEnd];
WriteEndPropertyElement(writer, lookups, storeEnd, modelEnd);
}
ReferentialConstraint constraint = GetReferentialConstraint(store);
foreach (EdmProperty fkColumn in constraint.ToProperties)
{
if (fkColumn.Nullable)
{
WriteConditionElement(writer, fkColumn);
}
}
writer.WriteEndElement();
}
private static void WriteConditionElement(XmlWriter writer, EdmProperty fkColumn)
{
writer.WriteStartElement(StorageMslConstructs.ConditionElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.ConditionColumnNameAttribute, fkColumn.Name);
writer.WriteAttributeString(StorageMslConstructs.ConditionIsNullAttribute, "false");
writer.WriteEndElement();
}
private static AssociationSetEnd GetAssociationSetEndForForeignKeyTable(AssociationSet store)
{
ReferentialConstraint constraint = GetReferentialConstraint(store);
return store.AssociationSetEnds.GetValue(constraint.ToRole.Name, false);
}
internal static ReferentialConstraint GetReferentialConstraint(AssociationSet set)
{
// this seeems like a hack, but it is what we have right now.
ReferentialConstraint constraint = null;
foreach (ReferentialConstraint rc in set.ElementType.ReferentialConstraints)
{
Debug.Assert(constraint == null, "we should only get one");
constraint = rc;
}
Debug.Assert(constraint != null, "we should get at least one constraint");
return constraint;
}
private static void WriteEndPropertyElement(XmlWriter writer, MappingLookups lookups, AssociationSetEnd store, AssociationSetEnd model)
{
writer.WriteStartElement(StorageMslConstructs.EndPropertyMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.EndPropertyMappingNameAttribute, model.Name);
foreach (EdmProperty storeKeyMember in store.EntitySet.ElementType.KeyMembers)
{
EdmProperty modelKeyMember = lookups.StoreEdmPropertyToModelEdmProperty[storeKeyMember];
EdmProperty storeFkTableMember = GetAssociatedFkColumn(store, storeKeyMember);
WriteScalarPropertyElement(writer, storeFkTableMember, modelKeyMember);
}
writer.WriteEndElement();
}
private static EdmProperty GetAssociatedFkColumn(AssociationSetEnd store, EdmProperty storeKeyProperty)
{
ReferentialConstraint constraint = GetReferentialConstraint(store.ParentAssociationSet);
if (store.Name == constraint.FromRole.Name)
{
for (int i = 0; i < constraint.FromProperties.Count; i++)
{
if (constraint.FromProperties[i] == storeKeyProperty)
{
// return the matching Fk column
return constraint.ToProperties[i];
}
}
}
return storeKeyProperty;
}
private static void WriteEntitySetMappingElement(XmlWriter writer, MappingLookups lookups, EntitySet store, EntitySet model)
{
writer.WriteStartElement(StorageMslConstructs.EntitySetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingStoreEntitySetAttribute, store.Name);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingTypeNameAttribute, model.ElementType.FullName);
foreach (EdmProperty storeProperty in store.ElementType.Properties)
{
// we don't add the fk properties to c-space, so some are missing,
// check to see if we have a map for this one
if (lookups.StoreEdmPropertyToModelEdmProperty.ContainsKey(storeProperty))
{
EdmProperty modelProperty = lookups.StoreEdmPropertyToModelEdmProperty[storeProperty];
WriteScalarPropertyElement(writer, storeProperty, modelProperty);
}
}
writer.WriteEndElement();
}
private static void WriteScalarPropertyElement(XmlWriter writer, EdmProperty store, EdmProperty model)
{
Debug.Assert(store.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType, "only expect scalar type properties");
Debug.Assert(model.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType, "only expect scalar type properties");
writer.WriteStartElement(StorageMslConstructs.ScalarPropertyElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.ScalarPropertyNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.ScalarPropertyColumnNameAttribute, store.Name);
writer.WriteEndElement();
}
private static void WriteMappingStartElement(XmlWriter writer)
{
writer.WriteStartElement(StorageMslConstructs.MappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.MappingSpaceAttribute, "C-S");
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Mapping;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Diagnostics;
using System.Xml;
using System.Data.Common.Utils;
using System.Linq;
namespace System.Data.Entity.Design.Common
{
internal static class OneToOneMappingSerializer
{
internal class MappingLookups
{
internal Dictionary StoreEntityTypeToModelEntityType = new Dictionary();
internal Dictionary StoreEdmPropertyToModelEdmProperty = new Dictionary();
internal Dictionary StoreEntitySetToModelEntitySet = new Dictionary();
internal Dictionary StoreAssociationTypeToModelAssociationType = new Dictionary();
internal Dictionary StoreAssociationEndMemberToModelAssociationEndMember = new Dictionary();
internal Dictionary StoreAssociationSetToModelAssociationSet = new Dictionary();
internal Dictionary StoreAssociationSetEndToModelAssociationSetEnd = new Dictionary();
internal List CollapsedEntityAssociationSets = new List();
}
// this class represents a construct found in the ssdl where a link table
// contained no data (all its properties were part of its keys)
// it has exactly two associations
// the entity type is the TO side of both associations
// all the colums are used as TO columns in the constraint
internal class CollapsedEntityAssociationSet
{
private EntitySet _storeEntitySet;
private List _storeAssociationSets = new List(2);
private AssociationSet _modelAssociationSet;
public AssociationSet ModelAssociationSet
{
get { return _modelAssociationSet; }
set
{
Debug.Assert(_modelAssociationSet == null, "why is this getting set multiple times, it should only be set after the new set is created");
_modelAssociationSet = value;
}
}
public CollapsedEntityAssociationSet(EntitySet entitySet)
{
Debug.Assert(entitySet != null, "entitySet parameter is null");
_storeEntitySet = entitySet;
}
public EntitySet EntitySet
{
get { return _storeEntitySet; }
}
public List AssociationSets
{
get { return _storeAssociationSets; }
}
public void GetStoreAssociationSetEnd(int index, out AssociationSetEnd storeAssociationSetEnd, out RelationshipMultiplicity multiplicity, out OperationAction deleteBehavior)
{
Debug.Assert(index >= 0 && index < AssociationSets.Count, "out of bounds dude!!");
Debug.Assert(AssociationSets.Count == 2, "This code depends on only having exactly two AssociationSets");
GetFromAssociationSetEnd(AssociationSets[index], AssociationSets[(index+1)%2], out storeAssociationSetEnd, out multiplicity, out deleteBehavior);
}
private void GetFromAssociationSetEnd(AssociationSet definingSet, AssociationSet multiplicitySet, out AssociationSetEnd associationSetEnd, out RelationshipMultiplicity multiplicity, out OperationAction deleteBehavior)
{
// for a situation like this (CD is CascadeDelete)
//
// -------- CD -------- CD --------
// | A |1 <- 1| AtoB |* <- 1| B |
// | |-------| |-------| |
// | | | | | |
// -------- -------- --------
//
// You get
// -------- CD --------
// | A |* <- 1| B |
// | |-------| |
// | | | |
// -------- --------
//
// Notice that the of the new "link table association" muliplicities are opposite of what comming into the original link table
// this seems counter intuitive at first, but makes sense when you think all the way through it
//
// CascadeDelete Behavior (we can assume the runtime will always delete cascade
// to the link table from the outside tables (it actually doesn't, but that is a bug))
// Store Effective
// A -> AToB <- B None
// A <- AToB <- B <-
// A -> AToB -> B ->
// A <- AToB -> B None
// A <- AToB B <-
// A AToB -> B ->
// A -> AToB B None
// A AToB <- B None
//
// Other CascadeDelete rules
// 1. Can't have a delete from a Many multiplicity end
// 2. Can't have a delete on both ends
//
associationSetEnd = GetAssociationSetEnd(definingSet, true);
AssociationSetEnd multiplicityAssociationSetEnd = GetAssociationSetEnd(multiplicitySet, false);
multiplicity = multiplicityAssociationSetEnd.CorrespondingAssociationEndMember.RelationshipMultiplicity;
deleteBehavior = OperationAction.None;
if (multiplicity != RelationshipMultiplicity.Many)
{
OperationAction otherEndBehavior = GetAssociationSetEnd(definingSet, false).CorrespondingAssociationEndMember.DeleteBehavior;
if(otherEndBehavior == OperationAction.None)
{
// Since the other end does not have an operation
// that means that only one end could possibly have an operation, that is good
// so set it the operation
deleteBehavior = multiplicityAssociationSetEnd.CorrespondingAssociationEndMember.DeleteBehavior;
}
}
}
private static AssociationSetEnd GetAssociationSetEnd(AssociationSet set, bool fromEnd)
{
Debug.Assert(set.ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[0]");
ReferentialConstraint constraint = set.ElementType.ReferentialConstraints[0];
Debug.Assert(set.AssociationSetEnds.Count == 2, "Associations are assumed to have two ends");
int toEndIndex, fromEndIndex;
if (set.AssociationSetEnds[0].CorrespondingAssociationEndMember == constraint.FromRole)
{
fromEndIndex = 0;
toEndIndex = 1;
}
else
{
fromEndIndex = 1;
toEndIndex = 0;
}
if (fromEnd)
{
return set.AssociationSetEnds[fromEndIndex];
}
else
{
return set.AssociationSetEnds[toEndIndex];
}
}
public bool MeetsRequirementsForCollapsableAssociation
{
get
{
if (_storeAssociationSets.Count != 2)
return false;
ReferentialConstraint constraint0;
ReferentialConstraint constraint1;
GetConstraints(out constraint0, out constraint1);
if (!IsEntityDependentSideOfBothAssociations(constraint0, constraint1))
return false;
if (!IsAtLeastOneColumnOfBothDependentRelationshipColumnSetsNonNullable(constraint0, constraint1))
return false;
if (!AreAllEntityColumnsMappedAsToColumns(constraint0, constraint1))
return false;
if (IsAtLeastOneColumnFKInBothAssociations(constraint0, constraint1))
return false;
return true;
}
}
private bool IsAtLeastOneColumnFKInBothAssociations(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return constraint1.ToProperties.Any(c => constraint0.ToProperties.Contains(c));
}
private bool IsAtLeastOneColumnOfBothDependentRelationshipColumnSetsNonNullable(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return ToPropertyHasNonNullableColumn(constraint0) && ToPropertyHasNonNullableColumn(constraint1);
}
private static bool ToPropertyHasNonNullableColumn(ReferentialConstraint constraint)
{
foreach (EdmProperty property in constraint.ToProperties)
{
if (!property.Nullable)
{
return true;
}
}
return false;
}
private bool AreAllEntityColumnsMappedAsToColumns(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
Set names = new Set();
AddToPropertyNames(constraint0, names);
AddToPropertyNames(constraint1, names);
return names.Count == _storeEntitySet.ElementType.Properties.Count;
}
private static void AddToPropertyNames(ReferentialConstraint constraint, Set names)
{
foreach (EdmProperty property in constraint.ToProperties)
{
names.Add(property.Name);
}
}
private bool IsEntityDependentSideOfBothAssociations(ReferentialConstraint constraint0, ReferentialConstraint constraint1)
{
return ((RefType)constraint0.ToRole.TypeUsage.EdmType).ElementType == _storeEntitySet.ElementType && ((RefType)constraint1.ToRole.TypeUsage.EdmType).ElementType == _storeEntitySet.ElementType;
}
private void GetConstraints(out ReferentialConstraint constraint0, out ReferentialConstraint constraint1)
{
Debug.Assert(_storeAssociationSets.Count == 2, "don't call this method if you don't have two associations");
Debug.Assert(_storeAssociationSets[0].ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[0]");
Debug.Assert(_storeAssociationSets[1].ElementType.ReferentialConstraints.Count == 1, "no referenctial constraint for association[1]");
constraint0 = _storeAssociationSets[0].ElementType.ReferentialConstraints[0];
constraint1 = _storeAssociationSets[1].ElementType.ReferentialConstraints[0];
}
}
public static void WriteXml(XmlWriter writer,
MappingLookups lookups,
EntityContainer storeContainer,
EntityContainer modelContainer)
{
EDesignUtil.CheckArgumentNull(writer, "writer");
EDesignUtil.CheckArgumentNull(storeContainer, "storeContainer");
EDesignUtil.CheckArgumentNull(modelContainer, "modelContainer");
WriteMappingStartElement(writer);
WriteEntityContainerMappingElement(writer, lookups, storeContainer, modelContainer );
writer.WriteEndElement();
}
private static void WriteEntityContainerMappingElement(XmlWriter writer, MappingLookups lookups, EntityContainer storeContainer, EntityContainer modelContainer)
{
writer.WriteStartElement(StorageMslConstructs.EntityContainerMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.StorageEntityContainerAttribute, storeContainer.Name);
writer.WriteAttributeString(StorageMslConstructs.CDMEntityContainerAttribute, modelContainer.Name);
foreach (EntitySet set in lookups.StoreEntitySetToModelEntitySet.Keys)
{
EntitySet modelEntitySet = lookups.StoreEntitySetToModelEntitySet[set];
WriteEntitySetMappingElement(writer, lookups, set, modelEntitySet);
}
foreach(AssociationSet set in lookups.StoreAssociationSetToModelAssociationSet.Keys)
{
AssociationSet modelAssociationSet = lookups.StoreAssociationSetToModelAssociationSet[set];
WriteAssociationSetMappingElement(writer, lookups, set, modelAssociationSet);
}
foreach (CollapsedEntityAssociationSet set in lookups.CollapsedEntityAssociationSets)
{
WriteAssociationSetMappingElement(writer, lookups, set);
}
writer.WriteEndElement();
}
private static void WriteAssociationSetMappingElement(XmlWriter writer, MappingLookups lookups, CollapsedEntityAssociationSet collapsedAssociationSet)
{
writer.WriteStartElement(StorageMslConstructs.AssociationSetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingNameAttribute, collapsedAssociationSet.ModelAssociationSet.Name);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingTypeNameAttribute, collapsedAssociationSet.ModelAssociationSet.ElementType.FullName);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingStoreEntitySetAttribute, collapsedAssociationSet.EntitySet.Name);
for (int i = 0; i < collapsedAssociationSet.AssociationSets.Count; i++)
{
AssociationSetEnd storeEnd;
RelationshipMultiplicity multiplicity;
OperationAction deleteBehavior;
collapsedAssociationSet.GetStoreAssociationSetEnd(i, out storeEnd, out multiplicity, out deleteBehavior);
AssociationSetEnd modelEnd = lookups.StoreAssociationSetEndToModelAssociationSetEnd[storeEnd];
WriteEndPropertyElement(writer, lookups, storeEnd, modelEnd);
}
// don't need condition element
writer.WriteEndElement();
}
private static void WriteAssociationSetMappingElement(XmlWriter writer, MappingLookups lookups, AssociationSet store, AssociationSet model)
{
writer.WriteStartElement(StorageMslConstructs.AssociationSetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingTypeNameAttribute, model.ElementType.FullName);
// all column names must be the primary key of the
// end, but as columns in the Fk table.
AssociationSetEnd foreignKeyTableEnd = GetAssociationSetEndForForeignKeyTable(store);
writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingStoreEntitySetAttribute, foreignKeyTableEnd.EntitySet.Name);
foreach (AssociationSetEnd storeEnd in store.AssociationSetEnds)
{
AssociationSetEnd modelEnd = lookups.StoreAssociationSetEndToModelAssociationSetEnd[storeEnd];
WriteEndPropertyElement(writer, lookups, storeEnd, modelEnd);
}
ReferentialConstraint constraint = GetReferentialConstraint(store);
foreach (EdmProperty fkColumn in constraint.ToProperties)
{
if (fkColumn.Nullable)
{
WriteConditionElement(writer, fkColumn);
}
}
writer.WriteEndElement();
}
private static void WriteConditionElement(XmlWriter writer, EdmProperty fkColumn)
{
writer.WriteStartElement(StorageMslConstructs.ConditionElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.ConditionColumnNameAttribute, fkColumn.Name);
writer.WriteAttributeString(StorageMslConstructs.ConditionIsNullAttribute, "false");
writer.WriteEndElement();
}
private static AssociationSetEnd GetAssociationSetEndForForeignKeyTable(AssociationSet store)
{
ReferentialConstraint constraint = GetReferentialConstraint(store);
return store.AssociationSetEnds.GetValue(constraint.ToRole.Name, false);
}
internal static ReferentialConstraint GetReferentialConstraint(AssociationSet set)
{
// this seeems like a hack, but it is what we have right now.
ReferentialConstraint constraint = null;
foreach (ReferentialConstraint rc in set.ElementType.ReferentialConstraints)
{
Debug.Assert(constraint == null, "we should only get one");
constraint = rc;
}
Debug.Assert(constraint != null, "we should get at least one constraint");
return constraint;
}
private static void WriteEndPropertyElement(XmlWriter writer, MappingLookups lookups, AssociationSetEnd store, AssociationSetEnd model)
{
writer.WriteStartElement(StorageMslConstructs.EndPropertyMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.EndPropertyMappingNameAttribute, model.Name);
foreach (EdmProperty storeKeyMember in store.EntitySet.ElementType.KeyMembers)
{
EdmProperty modelKeyMember = lookups.StoreEdmPropertyToModelEdmProperty[storeKeyMember];
EdmProperty storeFkTableMember = GetAssociatedFkColumn(store, storeKeyMember);
WriteScalarPropertyElement(writer, storeFkTableMember, modelKeyMember);
}
writer.WriteEndElement();
}
private static EdmProperty GetAssociatedFkColumn(AssociationSetEnd store, EdmProperty storeKeyProperty)
{
ReferentialConstraint constraint = GetReferentialConstraint(store.ParentAssociationSet);
if (store.Name == constraint.FromRole.Name)
{
for (int i = 0; i < constraint.FromProperties.Count; i++)
{
if (constraint.FromProperties[i] == storeKeyProperty)
{
// return the matching Fk column
return constraint.ToProperties[i];
}
}
}
return storeKeyProperty;
}
private static void WriteEntitySetMappingElement(XmlWriter writer, MappingLookups lookups, EntitySet store, EntitySet model)
{
writer.WriteStartElement(StorageMslConstructs.EntitySetMappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingStoreEntitySetAttribute, store.Name);
writer.WriteAttributeString(StorageMslConstructs.EntitySetMappingTypeNameAttribute, model.ElementType.FullName);
foreach (EdmProperty storeProperty in store.ElementType.Properties)
{
// we don't add the fk properties to c-space, so some are missing,
// check to see if we have a map for this one
if (lookups.StoreEdmPropertyToModelEdmProperty.ContainsKey(storeProperty))
{
EdmProperty modelProperty = lookups.StoreEdmPropertyToModelEdmProperty[storeProperty];
WriteScalarPropertyElement(writer, storeProperty, modelProperty);
}
}
writer.WriteEndElement();
}
private static void WriteScalarPropertyElement(XmlWriter writer, EdmProperty store, EdmProperty model)
{
Debug.Assert(store.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType, "only expect scalar type properties");
Debug.Assert(model.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType, "only expect scalar type properties");
writer.WriteStartElement(StorageMslConstructs.ScalarPropertyElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.ScalarPropertyNameAttribute, model.Name);
writer.WriteAttributeString(StorageMslConstructs.ScalarPropertyColumnNameAttribute, store.Name);
writer.WriteEndElement();
}
private static void WriteMappingStartElement(XmlWriter writer)
{
writer.WriteStartElement(StorageMslConstructs.MappingElement, StorageMslConstructs.NamespaceURI);
writer.WriteAttributeString(StorageMslConstructs.MappingSpaceAttribute, "C-S");
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConfigUtil.cs
- TextEditorTables.cs
- DocumentAutomationPeer.cs
- SQLGuid.cs
- NativeDirectoryServicesQueryAPIs.cs
- ConfigurationFileMap.cs
- CodeTypeParameter.cs
- ToolStripDropDownButton.cs
- PanelStyle.cs
- ChangePassword.cs
- LinqToSqlWrapper.cs
- LocalFileSettingsProvider.cs
- PointLightBase.cs
- FatalException.cs
- TypeDescriptorContext.cs
- NodeFunctions.cs
- ContainerSelectorActiveEvent.cs
- TempEnvironment.cs
- RouteTable.cs
- SqlFormatter.cs
- SettingsBase.cs
- ProxyOperationRuntime.cs
- BitmapCodecInfo.cs
- Accessible.cs
- Debug.cs
- ReferencedAssembly.cs
- GetWinFXPath.cs
- XmlCharType.cs
- FormsAuthenticationEventArgs.cs
- StubHelpers.cs
- WebBaseEventKeyComparer.cs
- SafeFileMappingHandle.cs
- EventLogPropertySelector.cs
- SchemaImporterExtensionElement.cs
- TabControlToolboxItem.cs
- HttpClientCertificate.cs
- DataObjectEventArgs.cs
- GACIdentityPermission.cs
- DataGridViewCellStyleChangedEventArgs.cs
- ControlParameter.cs
- ViewBase.cs
- UserControlDocumentDesigner.cs
- MeasureItemEvent.cs
- DoubleAnimationUsingPath.cs
- TypefaceMap.cs
- OdbcConnectionStringbuilder.cs
- _BasicClient.cs
- Point4D.cs
- AsyncContentLoadedEventArgs.cs
- FontStretch.cs
- ExpressionCopier.cs
- WsdlImporterElementCollection.cs
- IndentedWriter.cs
- CategoryAttribute.cs
- CDSsyncETWBCLProvider.cs
- HttpListenerPrefixCollection.cs
- ClearTypeHintValidation.cs
- HwndSubclass.cs
- BamlRecordReader.cs
- HttpHandlerAction.cs
- JulianCalendar.cs
- LayoutDump.cs
- TagMapCollection.cs
- OverflowException.cs
- AssemblyBuilder.cs
- DesignerOptionService.cs
- SocketInformation.cs
- BlobPersonalizationState.cs
- BinaryCommonClasses.cs
- SqlClientWrapperSmiStreamChars.cs
- VisualTarget.cs
- SignatureHelper.cs
- DocumentPageHost.cs
- EntityDescriptor.cs
- TdsParserHelperClasses.cs
- SliderAutomationPeer.cs
- WebPermission.cs
- elementinformation.cs
- ForEach.cs
- ReflectEventDescriptor.cs
- SoapExtensionReflector.cs
- DataGridColumnsPage.cs
- NoneExcludedImageIndexConverter.cs
- RegexGroup.cs
- WebRequest.cs
- Screen.cs
- Unit.cs
- ValidatingReaderNodeData.cs
- WriterOutput.cs
- RefreshEventArgs.cs
- InvalidAsynchronousStateException.cs
- HtmlElementEventArgs.cs
- TypeElement.cs
- DocumentPageViewAutomationPeer.cs
- FileDetails.cs
- NestedContainer.cs
- PropertyMap.cs
- WebPartConnectionsDisconnectVerb.cs
- Profiler.cs
- ObjectAssociationEndMapping.cs