1 //---------------------------------------------------------------------
2 // <copyright file="RecordConverter.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 
10 namespace System.Data.Mapping.Update.Internal
11 {
12     using System.Data.Entity;
13 
14     /// <summary>
15     /// Converts records to new instance expressions. Assumes that all inputs come from a single data reader (because
16     /// it caches record layout). If multiple readers are used, multiple converters must be constructed in case
17     /// the different readers return different layouts for types.
18     /// </summary>
19     /// <remarks>
20     /// Conventions for modifiedProperties enumeration: null means all properties are modified, empty means none,
21     /// non-empty means some.
22     /// </remarks>
23     internal class RecordConverter
24     {
25         #region Constructors
26         /// <summary>
27         /// Initializes a new converter given a command tree context. Initializes a new record layout cache.
28         /// </summary>
29         /// <param name="updateTranslator">Sets <see cref="m_updateTranslator" /></param>
RecordConverter(UpdateTranslator updateTranslator)30         internal RecordConverter(UpdateTranslator updateTranslator)
31         {
32             m_updateTranslator = updateTranslator;
33         }
34         #endregion
35 
36         #region Fields
37         /// <summary>
38         /// Context used to produce expressions.
39         /// </summary>
40         private UpdateTranslator m_updateTranslator;
41         #endregion
42 
43         #region Methods
44         /// <summary>
45         /// Converts original values in a state entry to a DbNewInstanceExpression. The record must be either an entity or
46         /// a relationship set instance.
47         /// </summary>
48         /// <remarks>
49         /// This method is not thread safe.
50         /// </remarks>
51         /// <param name="stateEntry">Gets state entry this record is associated with.</param>
52         /// <param name="modifiedPropertiesBehavior">Indicates how to determine whether a property is modified.</param>
53         /// <returns>New instance expression.</returns>
ConvertOriginalValuesToPropagatorResult(IEntityStateEntry stateEntry, ModifiedPropertiesBehavior modifiedPropertiesBehavior)54         internal PropagatorResult ConvertOriginalValuesToPropagatorResult(IEntityStateEntry stateEntry, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
55         {
56             return ConvertStateEntryToPropagatorResult(stateEntry, useCurrentValues: false, modifiedPropertiesBehavior: modifiedPropertiesBehavior);
57         }
58 
59         /// <summary>
60         /// Converts current values in a state entry to a DbNewInstanceExpression. The record must be either an entity or
61         /// a relationship set instance.
62         /// </summary>
63         /// <remarks>
64         /// This method is not thread safe.
65         /// </remarks>
66         /// <param name="stateEntry">Gets state entry this record is associated with.</param>
67         /// <param name="modifiedPropertiesBehavior">Indicates how to determine whether a property is modified.</param>
68         /// <returns>New instance expression.</returns>
ConvertCurrentValuesToPropagatorResult(IEntityStateEntry stateEntry, ModifiedPropertiesBehavior modifiedPropertiesBehavior)69         internal PropagatorResult ConvertCurrentValuesToPropagatorResult(IEntityStateEntry stateEntry, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
70         {
71             return ConvertStateEntryToPropagatorResult(stateEntry, useCurrentValues: true, modifiedPropertiesBehavior: modifiedPropertiesBehavior);
72         }
73 
ConvertStateEntryToPropagatorResult(IEntityStateEntry stateEntry, bool useCurrentValues, ModifiedPropertiesBehavior modifiedPropertiesBehavior)74         private PropagatorResult ConvertStateEntryToPropagatorResult(IEntityStateEntry stateEntry, bool useCurrentValues, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
75         {
76             try
77             {
78                 EntityUtil.CheckArgumentNull(stateEntry, "stateEntry");
79                 IExtendedDataRecord record = useCurrentValues
80                     ? EntityUtil.CheckArgumentNull(stateEntry.CurrentValues as IExtendedDataRecord, "stateEntry.CurrentValues")
81                     : EntityUtil.CheckArgumentNull(stateEntry.OriginalValues as IExtendedDataRecord, "stateEntry.OriginalValues");
82 
83                 bool isModified = false; // the root of the state entry is unchanged because the type is static
84                 return ExtractorMetadata.ExtractResultFromRecord(stateEntry, isModified, record, useCurrentValues, m_updateTranslator, modifiedPropertiesBehavior);
85             }
86             catch (Exception e)
87             {
88                 if (UpdateTranslator.RequiresContext(e))
89                 {
90                     throw EntityUtil.Update(Strings.Update_ErrorLoadingRecord, e, stateEntry);
91                 }
92                 throw;
93             }
94         }
95         #endregion
96     }
97 }
98