Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / SqlClient / SqlGen / DmlSqlGenerator.cs / 2 / DmlSqlGenerator.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;
using System.Data.Common.Utils;
using System.Data.Mapping.Update.Internal;
using System.Data.Mapping;
namespace System.Data.SqlClient.SqlGen
{
///
/// Class generating SQL for a DML command tree.
///
internal static class DmlSqlGenerator
{
private const int s_commandTextBuilderInitialCapacity = 256;
internal static string GenerateUpdateSql(DbUpdateCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
const string dummySetParameter = "@p";
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion);
if (tree.SetClauses.Count == 0)
{
commandText.AppendLine("declare " + dummySetParameter + " int");
}
// update [schemaName].[tableName]
commandText.Append("update ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// set c1 = ..., c2 = ..., ...
bool first = true;
commandText.Append("set ");
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Property.Accept(translator);
commandText.Append(" = ");
setClause.Value.Accept(translator);
}
if (first)
{
// If first is still true, it indicates there were no set
// clauses. Introduce a fake set clause so that:
// - we acquire the appropriate locks
// - server-gen columns (e.g. timestamp) get recomputed
//
// We use the following pattern:
//
// update Foo
// set @p = 0
// where ...
commandText.Append(dummySetParameter + " = 0");
}
commandText.AppendLine();
// where c1 = ..., c2 = ...
commandText.Append("where ");
tree.Predicate.Accept(translator);
commandText.AppendLine();
// generate returning sql
GenerateReturningSql(commandText, tree, translator, tree.Returning);
parameters = translator.Parameters;
return commandText.ToString();
}
internal static string GenerateDeleteSql(DbDeleteCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, false, sqlVersion);
// delete [schemaName].[tableName]
commandText.Append("delete ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// where c1 = ... AND c2 = ...
commandText.Append("where ");
tree.Predicate.Accept(translator);
parameters = translator.Parameters;
return commandText.ToString();
}
internal static string GenerateInsertSql(DbInsertCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree,
null != tree.Returning, sqlVersion);
// insert [schemaName].[tableName]
commandText.Append("insert ");
tree.Target.Expression.Accept(translator);
if (0 < tree.SetClauses.Count)
{
// (c1, c2, c3, ...)
commandText.Append("(");
bool first = true;
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Property.Accept(translator);
}
commandText.AppendLine(")");
// values c1, c2, ...
first = true;
commandText.Append("values (");
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Value.Accept(translator);
translator.RegisterMemberValue(setClause.Property, setClause.Value);
}
commandText.AppendLine(")");
}
else
{
// default values
commandText.AppendLine().AppendLine("default values");
}
// generate returning sql
GenerateReturningSql(commandText, tree, translator, tree.Returning);
parameters = translator.Parameters;
return commandText.ToString();
}
// Generates T-SQL describing a member
// Requires: member must belong to an entity type (a safe requirement for DML
// SQL gen, where we only access table columns)
private static string GenerateMemberTSql(EdmMember member)
{
EntityType entityType = (EntityType)member.DeclaringType;
string sql;
if (!entityType.TryGetMemberSql(member, out sql))
{
sql = SqlGenerator.QuoteIdentifier(member.Name);
entityType.SetMemberSql(member, sql);
}
return sql;
}
///
/// Generates SQL fragment returning server-generated values.
/// Requires: translator knows about member values so that we can figure out
/// how to construct the key predicate.
///
/// Sample SQL:
///
/// select IdentityValue
/// from dbo.MyTable
/// where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
///
/// or
///
/// select TimestamptValue
/// from dbo.MyTable
/// where @@ROWCOUNT > 0 and Id = 1
///
/// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
///
///
/// Builder containing command text
/// Modification command tree
/// Translator used to produce DML SQL statement
/// for the tree
/// Returning expression. If null, the method returns
/// immediately without producing a SELECT statement.
private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree,
ExpressionTranslator translator, DbExpression returning)
{
// Nothing to do if there is no Returning expression
if (null == returning) { return; }
// select
commandText.Append("select ");
returning.Accept(translator);
commandText.AppendLine();
// from
commandText.Append("from ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// where
commandText.Append("where @@ROWCOUNT > 0");
EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
bool identity = false;
foreach (EdmMember keyMember in table.ElementType.KeyMembers)
{
commandText.Append(" and ");
commandText.Append(GenerateMemberTSql(keyMember));
commandText.Append(" = ");
// retrieve member value sql. the translator remembers member values
// as it constructs the DML statement (which precedes the "returning"
// SQL)
SqlParameter value;
if (translator.MemberValues.TryGetValue(keyMember, out value))
{
commandText.Append(value.ParameterName);
}
else
{
// if no value is registered for the key member, it means it is an identity
// which can be retrieved using the scope_identity() function
if (identity)
{
// there can be only one server generated key
throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedServerGenKey(table.Name));
}
if (!IsValidIdentityColumnType(keyMember.TypeUsage))
{
throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_NotSupportedIdentityType(
keyMember.Name, keyMember.TypeUsage.ToString()));
}
commandText.Append("scope_identity()");
identity = true;
}
}
}
private static bool IsValidIdentityColumnType(TypeUsage typeUsage)
{
// SQL Server supports the following types for identity columns:
// tinyint, smallint, int, bigint, decimal(p,0), or numeric(p,0)
// make sure it's a primitive type
if (typeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
{
return false;
}
// check if this is a supported primitive type (compare by name)
string typeName = typeUsage.EdmType.Name;
// integer types
if (typeName == "tinyint" || typeName == "smallint" ||
typeName == "int" || typeName == "bigint")
{
return true;
}
// variable scale types (require scale = 0)
if (typeName == "decimal" || typeName == "numeric")
{
Facet scaleFacet;
return (typeUsage.Facets.TryGetValue(DbProviderManifest.ScaleFacetName,
false, out scaleFacet) && Convert.ToInt32(scaleFacet.Value, CultureInfo.InvariantCulture) == 0);
}
// type not in supported list
return false;
}
///
/// Lightweight expression translator for DML expression trees, which have constrained
/// scope and support.
///
private class ExpressionTranslator : BasicExpressionVisitor
{
///
/// Initialize a new expression translator populating the given string builder
/// with command text. Command text builder and command tree must not be null.
///
/// Command text with which to populate commands
/// Command tree generating SQL
/// Indicates whether the translator should preserve
/// member values while compiling t-SQL (only needed for server generation)
internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree,
bool preserveMemberValues, SqlVersion version)
{
Debug.Assert(null != commandText);
Debug.Assert(null != commandTree);
_commandText = commandText;
_commandTree = commandTree;
_version = version;
_parameters = new List();
_memberValues = preserveMemberValues ? new Dictionary() :
null;
}
private readonly StringBuilder _commandText;
private readonly DbModificationCommandTree _commandTree;
private readonly List _parameters;
private readonly Dictionary _memberValues;
private readonly static AliasGenerator s_parameterNames = new AliasGenerator("@", 1000);
private readonly SqlVersion _version;
internal List Parameters { get { return _parameters; } }
internal Dictionary MemberValues { get { return _memberValues; } }
// generate parameter (name based on parameter ordinal)
internal SqlParameter CreateParameter(object value, TypeUsage type)
{
// Suppress the MaxLength facet in the type usage because
// SqlClient will silently truncate data when SqlParameter.Size < |SqlParameter.Value|.
const bool ignoreMaxLengthFacet = true;
SqlParameter parameter = SqlProviderServices.CreateSqlParameter(s_parameterNames.GetName(_parameters.Count), type, ParameterMode.In, value, ignoreMaxLengthFacet, _version);
_parameters.Add(parameter);
return parameter;
}
public override void Visit(DbAndExpression expression)
{
VisitBinary(expression, " and ");
}
public override void Visit(DbOrExpression expression)
{
VisitBinary(expression, " or ");
}
public override void Visit(DbComparisonExpression expression)
{
Debug.Assert(expression.ExpressionKind == DbExpressionKind.Equals,
"only equals comparison expressions are produced in DML command trees in V1");
VisitBinary(expression, " = ");
RegisterMemberValue(expression.Left, expression.Right);
}
///
/// Call this method to register a property value pair so the translator "remembers"
/// the values for members of the row being modified. These values can then be used
/// to form a predicate for server-generation (based on the key of the row)
///
/// DbExpression containing the column reference (property expression).
/// DbExpression containing the value of the column.
internal void RegisterMemberValue(DbExpression propertyExpression, DbExpression value)
{
if (null != _memberValues)
{
// register the value for this property
Debug.Assert(propertyExpression.ExpressionKind == DbExpressionKind.Property,
"DML predicates and setters must be of the form property = value");
// get name of left property
EdmMember property = ((DbPropertyExpression)propertyExpression).Property;
// don't track null values
if (value.ExpressionKind != DbExpressionKind.Null)
{
Debug.Assert(value.ExpressionKind == DbExpressionKind.Constant,
"value must either constant or null");
// retrieve the last parameter added (which describes the parameter)
_memberValues[property] = _parameters[_parameters.Count - 1];
}
}
}
public override void Visit(DbIsNullExpression expression)
{
expression.Argument.Accept(this);
_commandText.Append(" is null");
}
public override void Visit(DbNotExpression expression)
{
_commandText.Append("not (");
expression.Accept(this);
_commandText.Append(")");
}
public override void Visit(DbConstantExpression expression)
{
SqlParameter parameter = CreateParameter(expression.Value, expression.ResultType);
_commandText.Append(parameter.ParameterName);
}
public override void Visit(DbScanExpression expression)
{
// we know we won't hit this code unless there is no function defined for this
// ModificationOperation, so if this EntitySet is using a DefiningQuery, instead
// of a table, that is an error
if (expression.Target.DefiningQuery != null)
{
string missingCudElement;
if (_commandTree.CommandTreeKind == DbCommandTreeKind.Delete)
{
missingCudElement = StorageMslConstructs.DeleteFunctionElement;
}
else if (_commandTree.CommandTreeKind == DbCommandTreeKind.Insert)
{
missingCudElement = StorageMslConstructs.InsertFunctionElement;
}
else
{
Debug.Assert(_commandTree.CommandTreeKind == DbCommandTreeKind.Update, "did you add a new option?");
missingCudElement = StorageMslConstructs.UpdateFunctionElement;
}
throw EntityUtil.Update(System.Data.Entity.Strings.Update_SqlEntitySetWithoutDmlFunctions(expression.Target.Name, missingCudElement, StorageMslConstructs.ModificationFunctionMappingElement), null);
}
_commandText.Append(SqlGenerator.GetTargetTSql(expression.Target));
}
public override void Visit(DbPropertyExpression expression)
{
_commandText.Append(GenerateMemberTSql(expression.Property));
}
public override void Visit(DbNullExpression expression)
{
_commandText.Append("null");
}
public override void Visit(DbNewInstanceExpression expression)
{
// assumes all arguments are self-describing (no need to use aliases
// because no renames are ever used in the projection)
bool first = true;
foreach (DbExpression argument in expression.Arguments)
{
if (first) { first = false; }
else { _commandText.Append(", "); }
argument.Accept(this);
}
}
private void VisitBinary(DbBinaryExpression expression, string separator)
{
_commandText.Append("(");
expression.Left.Accept(this);
_commandText.Append(separator);
expression.Right.Accept(this);
_commandText.Append(")");
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;
using System.Data.Common.Utils;
using System.Data.Mapping.Update.Internal;
using System.Data.Mapping;
namespace System.Data.SqlClient.SqlGen
{
///
/// Class generating SQL for a DML command tree.
///
internal static class DmlSqlGenerator
{
private const int s_commandTextBuilderInitialCapacity = 256;
internal static string GenerateUpdateSql(DbUpdateCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
const string dummySetParameter = "@p";
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, null != tree.Returning, sqlVersion);
if (tree.SetClauses.Count == 0)
{
commandText.AppendLine("declare " + dummySetParameter + " int");
}
// update [schemaName].[tableName]
commandText.Append("update ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// set c1 = ..., c2 = ..., ...
bool first = true;
commandText.Append("set ");
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Property.Accept(translator);
commandText.Append(" = ");
setClause.Value.Accept(translator);
}
if (first)
{
// If first is still true, it indicates there were no set
// clauses. Introduce a fake set clause so that:
// - we acquire the appropriate locks
// - server-gen columns (e.g. timestamp) get recomputed
//
// We use the following pattern:
//
// update Foo
// set @p = 0
// where ...
commandText.Append(dummySetParameter + " = 0");
}
commandText.AppendLine();
// where c1 = ..., c2 = ...
commandText.Append("where ");
tree.Predicate.Accept(translator);
commandText.AppendLine();
// generate returning sql
GenerateReturningSql(commandText, tree, translator, tree.Returning);
parameters = translator.Parameters;
return commandText.ToString();
}
internal static string GenerateDeleteSql(DbDeleteCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree, false, sqlVersion);
// delete [schemaName].[tableName]
commandText.Append("delete ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// where c1 = ... AND c2 = ...
commandText.Append("where ");
tree.Predicate.Accept(translator);
parameters = translator.Parameters;
return commandText.ToString();
}
internal static string GenerateInsertSql(DbInsertCommandTree tree, SqlVersion sqlVersion, out List parameters)
{
StringBuilder commandText = new StringBuilder(s_commandTextBuilderInitialCapacity);
ExpressionTranslator translator = new ExpressionTranslator(commandText, tree,
null != tree.Returning, sqlVersion);
// insert [schemaName].[tableName]
commandText.Append("insert ");
tree.Target.Expression.Accept(translator);
if (0 < tree.SetClauses.Count)
{
// (c1, c2, c3, ...)
commandText.Append("(");
bool first = true;
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Property.Accept(translator);
}
commandText.AppendLine(")");
// values c1, c2, ...
first = true;
commandText.Append("values (");
foreach (DbSetClause setClause in tree.SetClauses)
{
if (first) { first = false; }
else { commandText.Append(", "); }
setClause.Value.Accept(translator);
translator.RegisterMemberValue(setClause.Property, setClause.Value);
}
commandText.AppendLine(")");
}
else
{
// default values
commandText.AppendLine().AppendLine("default values");
}
// generate returning sql
GenerateReturningSql(commandText, tree, translator, tree.Returning);
parameters = translator.Parameters;
return commandText.ToString();
}
// Generates T-SQL describing a member
// Requires: member must belong to an entity type (a safe requirement for DML
// SQL gen, where we only access table columns)
private static string GenerateMemberTSql(EdmMember member)
{
EntityType entityType = (EntityType)member.DeclaringType;
string sql;
if (!entityType.TryGetMemberSql(member, out sql))
{
sql = SqlGenerator.QuoteIdentifier(member.Name);
entityType.SetMemberSql(member, sql);
}
return sql;
}
///
/// Generates SQL fragment returning server-generated values.
/// Requires: translator knows about member values so that we can figure out
/// how to construct the key predicate.
///
/// Sample SQL:
///
/// select IdentityValue
/// from dbo.MyTable
/// where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
///
/// or
///
/// select TimestamptValue
/// from dbo.MyTable
/// where @@ROWCOUNT > 0 and Id = 1
///
/// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
///
///
/// Builder containing command text
/// Modification command tree
/// Translator used to produce DML SQL statement
/// for the tree
/// Returning expression. If null, the method returns
/// immediately without producing a SELECT statement.
private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree,
ExpressionTranslator translator, DbExpression returning)
{
// Nothing to do if there is no Returning expression
if (null == returning) { return; }
// select
commandText.Append("select ");
returning.Accept(translator);
commandText.AppendLine();
// from
commandText.Append("from ");
tree.Target.Expression.Accept(translator);
commandText.AppendLine();
// where
commandText.Append("where @@ROWCOUNT > 0");
EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
bool identity = false;
foreach (EdmMember keyMember in table.ElementType.KeyMembers)
{
commandText.Append(" and ");
commandText.Append(GenerateMemberTSql(keyMember));
commandText.Append(" = ");
// retrieve member value sql. the translator remembers member values
// as it constructs the DML statement (which precedes the "returning"
// SQL)
SqlParameter value;
if (translator.MemberValues.TryGetValue(keyMember, out value))
{
commandText.Append(value.ParameterName);
}
else
{
// if no value is registered for the key member, it means it is an identity
// which can be retrieved using the scope_identity() function
if (identity)
{
// there can be only one server generated key
throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedServerGenKey(table.Name));
}
if (!IsValidIdentityColumnType(keyMember.TypeUsage))
{
throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_NotSupportedIdentityType(
keyMember.Name, keyMember.TypeUsage.ToString()));
}
commandText.Append("scope_identity()");
identity = true;
}
}
}
private static bool IsValidIdentityColumnType(TypeUsage typeUsage)
{
// SQL Server supports the following types for identity columns:
// tinyint, smallint, int, bigint, decimal(p,0), or numeric(p,0)
// make sure it's a primitive type
if (typeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
{
return false;
}
// check if this is a supported primitive type (compare by name)
string typeName = typeUsage.EdmType.Name;
// integer types
if (typeName == "tinyint" || typeName == "smallint" ||
typeName == "int" || typeName == "bigint")
{
return true;
}
// variable scale types (require scale = 0)
if (typeName == "decimal" || typeName == "numeric")
{
Facet scaleFacet;
return (typeUsage.Facets.TryGetValue(DbProviderManifest.ScaleFacetName,
false, out scaleFacet) && Convert.ToInt32(scaleFacet.Value, CultureInfo.InvariantCulture) == 0);
}
// type not in supported list
return false;
}
///
/// Lightweight expression translator for DML expression trees, which have constrained
/// scope and support.
///
private class ExpressionTranslator : BasicExpressionVisitor
{
///
/// Initialize a new expression translator populating the given string builder
/// with command text. Command text builder and command tree must not be null.
///
/// Command text with which to populate commands
/// Command tree generating SQL
/// Indicates whether the translator should preserve
/// member values while compiling t-SQL (only needed for server generation)
internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree,
bool preserveMemberValues, SqlVersion version)
{
Debug.Assert(null != commandText);
Debug.Assert(null != commandTree);
_commandText = commandText;
_commandTree = commandTree;
_version = version;
_parameters = new List();
_memberValues = preserveMemberValues ? new Dictionary() :
null;
}
private readonly StringBuilder _commandText;
private readonly DbModificationCommandTree _commandTree;
private readonly List _parameters;
private readonly Dictionary _memberValues;
private readonly static AliasGenerator s_parameterNames = new AliasGenerator("@", 1000);
private readonly SqlVersion _version;
internal List Parameters { get { return _parameters; } }
internal Dictionary MemberValues { get { return _memberValues; } }
// generate parameter (name based on parameter ordinal)
internal SqlParameter CreateParameter(object value, TypeUsage type)
{
// Suppress the MaxLength facet in the type usage because
// SqlClient will silently truncate data when SqlParameter.Size < |SqlParameter.Value|.
const bool ignoreMaxLengthFacet = true;
SqlParameter parameter = SqlProviderServices.CreateSqlParameter(s_parameterNames.GetName(_parameters.Count), type, ParameterMode.In, value, ignoreMaxLengthFacet, _version);
_parameters.Add(parameter);
return parameter;
}
public override void Visit(DbAndExpression expression)
{
VisitBinary(expression, " and ");
}
public override void Visit(DbOrExpression expression)
{
VisitBinary(expression, " or ");
}
public override void Visit(DbComparisonExpression expression)
{
Debug.Assert(expression.ExpressionKind == DbExpressionKind.Equals,
"only equals comparison expressions are produced in DML command trees in V1");
VisitBinary(expression, " = ");
RegisterMemberValue(expression.Left, expression.Right);
}
///
/// Call this method to register a property value pair so the translator "remembers"
/// the values for members of the row being modified. These values can then be used
/// to form a predicate for server-generation (based on the key of the row)
///
/// DbExpression containing the column reference (property expression).
/// DbExpression containing the value of the column.
internal void RegisterMemberValue(DbExpression propertyExpression, DbExpression value)
{
if (null != _memberValues)
{
// register the value for this property
Debug.Assert(propertyExpression.ExpressionKind == DbExpressionKind.Property,
"DML predicates and setters must be of the form property = value");
// get name of left property
EdmMember property = ((DbPropertyExpression)propertyExpression).Property;
// don't track null values
if (value.ExpressionKind != DbExpressionKind.Null)
{
Debug.Assert(value.ExpressionKind == DbExpressionKind.Constant,
"value must either constant or null");
// retrieve the last parameter added (which describes the parameter)
_memberValues[property] = _parameters[_parameters.Count - 1];
}
}
}
public override void Visit(DbIsNullExpression expression)
{
expression.Argument.Accept(this);
_commandText.Append(" is null");
}
public override void Visit(DbNotExpression expression)
{
_commandText.Append("not (");
expression.Accept(this);
_commandText.Append(")");
}
public override void Visit(DbConstantExpression expression)
{
SqlParameter parameter = CreateParameter(expression.Value, expression.ResultType);
_commandText.Append(parameter.ParameterName);
}
public override void Visit(DbScanExpression expression)
{
// we know we won't hit this code unless there is no function defined for this
// ModificationOperation, so if this EntitySet is using a DefiningQuery, instead
// of a table, that is an error
if (expression.Target.DefiningQuery != null)
{
string missingCudElement;
if (_commandTree.CommandTreeKind == DbCommandTreeKind.Delete)
{
missingCudElement = StorageMslConstructs.DeleteFunctionElement;
}
else if (_commandTree.CommandTreeKind == DbCommandTreeKind.Insert)
{
missingCudElement = StorageMslConstructs.InsertFunctionElement;
}
else
{
Debug.Assert(_commandTree.CommandTreeKind == DbCommandTreeKind.Update, "did you add a new option?");
missingCudElement = StorageMslConstructs.UpdateFunctionElement;
}
throw EntityUtil.Update(System.Data.Entity.Strings.Update_SqlEntitySetWithoutDmlFunctions(expression.Target.Name, missingCudElement, StorageMslConstructs.ModificationFunctionMappingElement), null);
}
_commandText.Append(SqlGenerator.GetTargetTSql(expression.Target));
}
public override void Visit(DbPropertyExpression expression)
{
_commandText.Append(GenerateMemberTSql(expression.Property));
}
public override void Visit(DbNullExpression expression)
{
_commandText.Append("null");
}
public override void Visit(DbNewInstanceExpression expression)
{
// assumes all arguments are self-describing (no need to use aliases
// because no renames are ever used in the projection)
bool first = true;
foreach (DbExpression argument in expression.Arguments)
{
if (first) { first = false; }
else { _commandText.Append(", "); }
argument.Accept(this);
}
}
private void VisitBinary(DbBinaryExpression expression, string separator)
{
_commandText.Append("(");
expression.Left.Accept(this);
_commandText.Append(separator);
expression.Right.Accept(this);
_commandText.Append(")");
}
}
}
}
// 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
- PromptStyle.cs
- InputGestureCollection.cs
- PriorityQueue.cs
- PerformanceCounter.cs
- ListDesigner.cs
- StatusBar.cs
- basenumberconverter.cs
- DynamicValueConverter.cs
- Effect.cs
- PreProcessInputEventArgs.cs
- GridViewUpdatedEventArgs.cs
- SelectionRange.cs
- NetworkInformationPermission.cs
- QilFunction.cs
- PresentationTraceSources.cs
- IisTraceListener.cs
- TemplateField.cs
- ListItemCollection.cs
- TextDocumentView.cs
- TextElement.cs
- DataGridCellEditEndingEventArgs.cs
- ViewStateModeByIdAttribute.cs
- SerializationUtilities.cs
- CommandBinding.cs
- AppSettingsExpressionBuilder.cs
- ping.cs
- FactoryId.cs
- Dump.cs
- IdentityNotMappedException.cs
- BasePattern.cs
- PropertyDescriptor.cs
- UIPropertyMetadata.cs
- TransformerTypeCollection.cs
- InitializeCorrelation.cs
- Journal.cs
- CompareInfo.cs
- CapabilitiesSection.cs
- SystemShuttingDownException.cs
- ExcCanonicalXml.cs
- ServiceNameElement.cs
- ToolboxComponentsCreatedEventArgs.cs
- Binding.cs
- OrthographicCamera.cs
- XpsFilter.cs
- DataBoundControlParameterTarget.cs
- TabletCollection.cs
- HtmlImage.cs
- TypedTableBaseExtensions.cs
- AttributeCollection.cs
- JpegBitmapDecoder.cs
- NullableDecimalAverageAggregationOperator.cs
- FlowNode.cs
- PrinterResolution.cs
- RemoteCryptoSignHashRequest.cs
- NativeMethods.cs
- SystemDropShadowChrome.cs
- StringValidatorAttribute.cs
- PackageFilter.cs
- DesignerLabelAdapter.cs
- PhotoPrintingIntent.cs
- CheckBoxFlatAdapter.cs
- XmlSchemaCollection.cs
- RequestCachePolicy.cs
- ProcessInfo.cs
- SmiContext.cs
- NativeMethods.cs
- ComponentManagerBroker.cs
- ResourceReferenceExpression.cs
- DatatypeImplementation.cs
- OracleConnection.cs
- OptimalBreakSession.cs
- ContentPathSegment.cs
- SynchronizationHandlesCodeDomSerializer.cs
- ZipArchive.cs
- CodeTypeReferenceCollection.cs
- SafeNativeMethods.cs
- BitmapFrameDecode.cs
- mda.cs
- EndOfStreamException.cs
- ChineseLunisolarCalendar.cs
- DataContext.cs
- SoapExtensionReflector.cs
- MatrixValueSerializer.cs
- Registration.cs
- XamlInt32CollectionSerializer.cs
- PathData.cs
- ListDesigner.cs
- HtmlAnchor.cs
- SortAction.cs
- Encoding.cs
- ButtonPopupAdapter.cs
- DesignerToolboxInfo.cs
- Events.cs
- NotificationContext.cs
- RowToFieldTransformer.cs
- Converter.cs
- LicenseProviderAttribute.cs
- DateTimeValueSerializer.cs
- ObjectDataSourceDesigner.cs
- SplashScreen.cs