Remove SELECT * from edit/initialize Query (#288)

* Major refactor of EditDataMetadata providers

* EditMetadataFactory generates "basic" EditTableMetadata objects based entirely on SMO metadata
* SmoEditTableMetadata no longer depends on SMO, making it unecessary to mock it
* Renamed SmoEditTableMetadata to EditTableMetadata
* EditTableMetadata can be extended with DbColumnWrappers

* Moving logic for extending a EditColumnMetadata into that class

* I *think* this will work for async execution of initialize tasks

* Fixing unit tests for new Edit(Table|Column)Metadata classes

* Async stuff that works! And passes unit tests

* Adding unit tests
Adding .idea to gitignore

* Adding message to the EditSessionReadyEvent

* Fixes from dev merge

* Fixing unit tests that Rider didn't catch as failing
May have been a bit heavy-handed with the async/await stuff

* Couple changes as per PR comments
This commit is contained in:
Benjamin Russell
2017-03-22 10:53:24 -07:00
committed by GitHub
parent d7ecfb1a87
commit 16b3874f28
30 changed files with 2325 additions and 1417 deletions

View File

@@ -14,6 +14,12 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
/// </summary>
public string OwnerUri { get; set; }
/// <summary>
/// Message to explain why a session failed. Should only be set when <see cref="Success"/>
/// is <c>false</c>.
/// </summary>
public string Message { get; set; }
/// <summary>
/// Whether or not the session is ready
/// </summary>

View File

@@ -0,0 +1,113 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Data;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
/// <summary>
/// Small class that stores information needed by the edit data service to properly process
/// edits into scripts.
/// </summary>
public class EditColumnMetadata
{
/// <summary>
/// Constructs a simple edit column metadata provider
/// </summary>
public EditColumnMetadata()
{
HasExtendedProperties = false;
}
#region Basic Properties (properties provided by SMO)
/// <summary>
/// If set, this is a string representation of the default value. If set to null, then the
/// column does not have a default value.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Escaped identifier for the name of the column
/// </summary>
public string EscapedName { get; set; }
/// <summary>
/// Whether or not the column is computed
/// </summary>
public bool IsComputed { get; set; }
/// <summary>
/// Whether or not the column is deterministically computed
/// </summary>
public bool IsDeterministic { get; set; }
/// <summary>
/// Whether or not the column is an identity column
/// </summary>
public bool IsIdentity { get; set; }
/// <summary>
/// The ordinal ID of the column
/// </summary>
public int Ordinal { get; set; }
#endregion
#region Extended Properties (properties provided by SqlClient)
public DbColumnWrapper DbColumn { get; private set; }
/// <summary>
/// Whether or not the column has extended properties
/// </summary>
public bool HasExtendedProperties { get; private set; }
/// <summary>
/// Whether or not the column is calculated on the server side. This could be a computed
/// column or a identity column.
/// </summary>
public bool? IsCalculated { get; private set; }
/// <summary>
/// Whether or not the column is used in a key to uniquely identify a row
/// </summary>
public bool? IsKey { get; private set; }
/// <summary>
/// Whether or not the column can be trusted for uniqueness
/// </summary>
public bool? IsTrustworthyForUniqueness { get; private set; }
#endregion
/// <summary>
/// Extracts extended column properties from the database columns from SQL Client
/// </summary>
/// <param name="dbColumn">The column information provided by SQL Client</param>
public void Extend(DbColumnWrapper dbColumn)
{
Validate.IsNotNull(nameof(dbColumn), dbColumn);
DbColumn = dbColumn;
// A column is trustworthy for uniqueness if it can be updated or it has an identity
// property. If both of these are false (eg, timestamp) we can't trust it to uniquely
// identify a row in the table
IsTrustworthyForUniqueness = dbColumn.IsUpdatable || dbColumn.IsIdentity.HasTrue();
// A key column is determined by whether it is a key
IsKey = dbColumn.IsKey;
// A column is calculated if it is identity, computed, or otherwise not updatable
IsCalculated = IsIdentity || IsComputed || !dbColumn.IsUpdatable;
// Mark the column as extended
HasExtendedProperties = true;
}
}
}

View File

@@ -1,53 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
/// <summary>
/// Small class that stores information needed by the edit data service to properly process
/// edits into scripts.
/// </summary>
public class EditColumnWrapper
{
/// <summary>
/// The DB column
/// </summary>
public DbColumnWrapper DbColumn { get; set; }
/// <summary>
/// If set, this is a string representation of the default value. If set to null, then the
/// column does not have a default value.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Escaped identifier for the name of the column
/// </summary>
public string EscapedName { get; set; }
/// <summary>
/// Whether or not the column is calculated on the server side. This could be a computed
/// column or a identity column.
/// </summary>
public bool IsCalculated { get; set; }
/// <summary>
/// Whether or not the column is used in a key to uniquely identify a row
/// </summary>
public bool IsKey { get; set; }
/// <summary>
/// Whether or not the column can be trusted for uniqueness
/// </summary>
public bool IsTrustworthyForUniqueness { get; set; }
/// <summary>
/// The ordinal ID of the column
/// </summary>
public int Ordinal { get; set; }
}
}

View File

@@ -13,7 +13,6 @@ using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType;
@@ -57,10 +56,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
private readonly Lazy<ConcurrentDictionary<string, EditSession>> editSessions = new Lazy<ConcurrentDictionary<string, EditSession>>(
() => new ConcurrentDictionary<string, EditSession>());
private readonly Lazy<ConcurrentDictionary<string, TaskCompletionSource<bool>>> initializeWaitHandles =
new Lazy<ConcurrentDictionary<string, TaskCompletionSource<bool>>>(
() => new ConcurrentDictionary<string, TaskCompletionSource<bool>>());
#endregion
#region Properties
@@ -70,12 +65,6 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// </summary>
internal ConcurrentDictionary<string, EditSession> ActiveSessions => editSessions.Value;
/// <summary>
/// Dictionary mapping OwnerURIs to wait handlers for initialize tasks. Pretty much only
/// provided for unit test scenarios.
/// </summary>
internal ConcurrentDictionary<string, TaskCompletionSource<bool>> InitializeWaitHandles => initializeWaitHandles.Value;
#endregion
/// <summary>
@@ -159,63 +148,32 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
internal async Task HandleInitializeRequest(EditInitializeParams initParams,
RequestContext<EditInitializeResult> requestContext)
{
Func<Exception, Task> executionFailureHandler = (e) => SendSessionReadyEvent(requestContext, initParams.OwnerUri, false, e.Message);
Func<Task> executionSuccessHandler = () => SendSessionReadyEvent(requestContext, initParams.OwnerUri, true, null);
EditSession.Connector connector = () => connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
EditSession.QueryRunner queryRunner = q => SessionInitializeQueryRunner(initParams.OwnerUri, requestContext, q);
try
{
{
// Make sure we have info to process this request
Validate.IsNotNullOrWhitespaceString(nameof(initParams.OwnerUri), initParams.OwnerUri);
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectName), initParams.ObjectName);
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
// Try to add a new wait handler to the
if (!InitializeWaitHandles.TryAdd(initParams.OwnerUri, new TaskCompletionSource<bool>()))
// Create a session and add it to the session list
EditSession session = new EditSession(metadataFactory, initParams.ObjectName, initParams.ObjectType);
if (!ActiveSessions.TryAdd(initParams.OwnerUri, session))
{
throw new InvalidOperationException(SR.EditDataInitializeInProgress);
throw new InvalidOperationException(SR.EditDataSessionAlreadyExists);
}
// Setup a callback for when the query has successfully created
Func<Query, Task<bool>> queryCreateSuccessCallback = async query =>
{
await requestContext.SendResult(new EditInitializeResult());
return true;
};
// Setup a callback for when the query failed to be created
Func<string, Task> queryCreateFailureCallback = async message =>
{
await requestContext.SendError(message);
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
};
// Setup a callback for when the query completes execution successfully
Query.QueryAsyncEventHandler queryCompleteSuccessCallback =
q => QueryCompleteCallback(q, initParams, requestContext);
// Setup a callback for when the query completes execution with failure
Query.QueryAsyncEventHandler queryCompleteFailureCallback = async query =>
{
EditSessionReadyParams readyParams = new EditSessionReadyParams
{
OwnerUri = initParams.OwnerUri,
Success = false
};
await requestContext.SendEvent(EditSessionReadyEvent.Type, readyParams);
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
};
// Put together a query for the results and execute it
ExecuteStringParams executeParams = new ExecuteStringParams
{
Query = $"SELECT * FROM {SqlScriptFormatter.FormatMultipartIdentifier(initParams.ObjectName)}",
OwnerUri = initParams.OwnerUri
};
await queryExecutionService.InterServiceExecuteQuery(executeParams, requestContext,
queryCreateSuccessCallback, queryCreateFailureCallback,
queryCompleteSuccessCallback, queryCompleteFailureCallback);
// Initialize the session
session.Initialize(connector, queryRunner, executionSuccessHandler, executionFailureHandler);
}
catch (Exception e)
{
await requestContext.SendError(e.Message);
CompleteInitializeWaitHandler(initParams.OwnerUri, false);
}
}
@@ -313,52 +271,64 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
return editSession;
}
private async Task QueryCompleteCallback(Query query, EditInitializeParams initParams,
IEventSender requestContext)
private async Task<EditSession.EditSessionQueryExecutionState> SessionInitializeQueryRunner(string ownerUri,
IEventSender eventSender, string query)
{
EditSessionReadyParams readyParams = new EditSessionReadyParams
// Open a task completion source, effectively creating a synchronous block
TaskCompletionSource<EditSession.EditSessionQueryExecutionState> taskCompletion =
new TaskCompletionSource<EditSession.EditSessionQueryExecutionState>();
// Setup callback for successful query creation
// NOTE: We do not want to set the task completion source, since we will continue executing the query after
Func<Query, Task<bool>> queryCreateSuccessCallback = q => Task.FromResult(true);
// Setup callback for failed query creation
Func<string, Task> queryCreateFailureCallback = m =>
{
OwnerUri = initParams.OwnerUri
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null, m));
return Task.FromResult(0);
};
try
// Setup callback for successful query execution
Query.QueryAsyncEventHandler queryCompleteSuccessCallback = q =>
{
// Validate the query for a editSession
ResultSet resultSet = EditSession.ValidateQueryForSession(query);
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(q));
return Task.FromResult(0);
};
// Get a connection we'll use for SMO metadata lookup (and committing, later on)
DbConnection conn = await connectionService.GetOrOpenConnection(initParams.OwnerUri, ConnectionType.Edit);
var metadata = metadataFactory.GetObjectMetadata(conn, resultSet.Columns,
initParams.ObjectName, initParams.ObjectType);
// Create the editSession and add it to the sessions list
EditSession editSession = new EditSession(resultSet, metadata);
if (!ActiveSessions.TryAdd(initParams.OwnerUri, editSession))
{
throw new InvalidOperationException("Failed to create edit editSession, editSession already exists.");
}
readyParams.Success = true;
}
catch (Exception)
// Setup callback for failed query execution
Query.QueryAsyncEventHandler queryCompleteFailureCallback = q =>
{
// Request that the query be disposed
await queryExecutionService.InterServiceDisposeQuery(initParams.OwnerUri, null, null);
readyParams.Success = false;
}
taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null));
return Task.FromResult(0);
};
// Send the edit session ready notification
await requestContext.SendEvent(EditSessionReadyEvent.Type, readyParams);
CompleteInitializeWaitHandler(initParams.OwnerUri, true);
// Execute the query
ExecuteStringParams executeParams = new ExecuteStringParams
{
Query = query,
OwnerUri = ownerUri
};
await queryExecutionService.InterServiceExecuteQuery(executeParams, eventSender,
queryCreateSuccessCallback, queryCreateFailureCallback,
queryCompleteSuccessCallback, queryCompleteFailureCallback);
// Wait for the completion source to complete, this will wait until the query has
// completed and sent all its events.
return await taskCompletion.Task;
}
private void CompleteInitializeWaitHandler(string ownerUri, bool result)
private static Task SendSessionReadyEvent(IEventSender eventSender, string ownerUri, bool success,
string message)
{
// If there isn't a wait handler, just ignore it
TaskCompletionSource<bool> initializeWaiter;
if (ownerUri != null && InitializeWaitHandles.TryRemove(ownerUri, out initializeWaiter))
var sessionReadyParams = new EditSessionReadyParams
{
initializeWaiter.SetResult(result);
}
OwnerUri = ownerUri,
Message = message,
Success = success
};
return eventSender.SendEvent(EditSessionReadyEvent.Type, sessionReadyParams);
}
#endregion

View File

@@ -25,28 +25,37 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
public class EditSession
{
private readonly ResultSet associatedResultSet;
private readonly IEditTableMetadata objectMetadata;
private ResultSet associatedResultSet;
private readonly IEditMetadataFactory metadataFactory;
private EditTableMetadata objectMetadata;
private readonly string objectName;
private readonly string objectType;
/// <summary>
/// Constructs a new edit session bound to the result set and metadat object provided
/// </summary>
/// <param name="resultSet">The result set of the table to be edited</param>
/// <param name="objMetadata">Metadata provider for the table to be edited</param>
public EditSession(ResultSet resultSet, IEditTableMetadata objMetadata)
/// <param name="metaFactory">Factory for creating metadata</param>
/// <param name="objName">The name of the object to edit</param>
/// <param name="objType">The type of the object to edit</param>
public EditSession(IEditMetadataFactory metaFactory, string objName, string objType)
{
Validate.IsNotNull(nameof(resultSet), resultSet);
Validate.IsNotNull(nameof(objMetadata), objMetadata);
Validate.IsNotNull(nameof(metaFactory), metaFactory);
Validate.IsNotNullOrWhitespaceString(nameof(objName), objName);
Validate.IsNotNullOrWhitespaceString(nameof(objType), objType);
// Setup the internal state
associatedResultSet = resultSet;
objectMetadata = objMetadata;
NextRowId = associatedResultSet.RowCount;
EditCache = new ConcurrentDictionary<long, RowEditBase>();
metadataFactory = metaFactory;
objectName = objName;
objectType = objType;
}
#region Properties
public delegate Task<DbConnection> Connector();
public delegate Task<EditSessionQueryExecutionState> QueryRunner(string query);
/// <summary>
/// The task that is running to commit the changes to the db
/// Internal for unit test purposes.
@@ -61,12 +70,43 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <summary>
/// The cache of pending updates. Internal for unit test purposes only
/// </summary>
internal ConcurrentDictionary<long, RowEditBase> EditCache { get; }
internal ConcurrentDictionary<long, RowEditBase> EditCache { get; private set; }
/// <summary>
/// The task that is running to initialize the edit session
/// </summary>
internal Task InitializeTask { get; set; }
/// <summary>
/// Whether or not the session has been initialized
/// </summary>
public bool IsInitialized { get; internal set; }
#endregion
#region Public Methods
public void Initialize(Connector connector, QueryRunner queryRunner, Func<Task> successHandler, Func<Exception, Task> errorHandler)
{
if (IsInitialized)
{
throw new InvalidOperationException(SR.EditDataSessionAlreadyInitialized);
}
if (InitializeTask != null)
{
throw new InvalidOperationException(SR.EditDataSessionAlreadyInitializing);
}
Validate.IsNotNull(nameof(connector), connector);
Validate.IsNotNull(nameof(queryRunner), queryRunner);
Validate.IsNotNull(nameof(successHandler), successHandler);
Validate.IsNotNull(nameof(errorHandler), errorHandler);
// Start up the initialize process
InitializeTask = InitializeInternal(connector, queryRunner, successHandler, errorHandler);
}
/// <summary>
/// Validates that a query can be used for an edit session. The target result set is returned
/// </summary>
@@ -100,6 +140,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <returns>The internal ID of the newly created row</returns>
public EditCreateRowResult CreateRow()
{
ThrowIfNotInitialized();
// Create a new row ID (atomically, since this could be accesses concurrently)
long newRowId = NextRowId++;
@@ -113,13 +155,13 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
}
// Set the default values of the row if we know them
string[] defaultValues = new string[objectMetadata.Columns.Count];
for(int i = 0; i < objectMetadata.Columns.Count; i++)
string[] defaultValues = new string[objectMetadata.Columns.Length];
for(int i = 0; i < objectMetadata.Columns.Length; i++)
{
EditColumnWrapper col = objectMetadata.Columns[i];
EditColumnMetadata col = objectMetadata.Columns[i];
// If the column is calculated, return the calculated placeholder as the display value
if (col.IsCalculated)
if (col.IsCalculated.HasTrue())
{
defaultValues[i] = SR.EditDataComputedColumnPlaceholder;
}
@@ -150,6 +192,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <param name="errorHandler">Callback to perform if the commit process has failed at some point</param>
public void CommitEdits(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
{
ThrowIfNotInitialized();
Validate.IsNotNull(nameof(connection), connection);
Validate.IsNotNull(nameof(successHandler), successHandler);
Validate.IsNotNull(nameof(errorHandler), errorHandler);
@@ -173,6 +217,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <param name="rowId">The internal ID of the row to delete</param>
public void DeleteRow(long rowId)
{
ThrowIfNotInitialized();
// Sanity check the row ID
if (rowId >= NextRowId || rowId < 0)
{
@@ -196,6 +242,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <returns>An array of rows with pending edits applied</returns>
public async Task<EditRow[]> GetRows(long startIndex, int rowCount)
{
ThrowIfNotInitialized();
// Get the cached rows from the result set
ResultSetSubset cachedRows = startIndex < associatedResultSet.RowCount
? await associatedResultSet.GetSubset(startIndex, rowCount)
@@ -249,6 +297,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <returns>String version of the old value for the cell</returns>
public string RevertCell(long rowId, int columnId)
{
ThrowIfNotInitialized();
// Attempt to get the row edit with the given ID
RowEditBase pendingEdit;
if (!EditCache.TryGetValue(rowId, out pendingEdit))
@@ -269,6 +319,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <param name="rowId">The internal ID of the row to reset</param>
public void RevertRow(long rowId)
{
ThrowIfNotInitialized();
// Attempt to remove the row with the given ID
RowEditBase removedEdit;
if (!EditCache.TryRemove(rowId, out removedEdit))
@@ -284,6 +336,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <returns></returns>
public string ScriptEdits(string outputPath)
{
ThrowIfNotInitialized();
// Validate the output path
// @TODO: Reinstate this code once we have an interface around file generation
//if (outputPath == null)
@@ -328,6 +382,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// <param name="newValue">The new string value of the cell to update</param>
public EditUpdateCellResult UpdateCell(long rowId, int columnId, string newValue)
{
ThrowIfNotInitialized();
// Sanity check to make sure that the row ID is in the range of possible values
if (rowId >= NextRowId || rowId < 0)
{
@@ -347,6 +403,38 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
#endregion
private async Task InitializeInternal(Connector connector, QueryRunner queryRunner,
Func<Task> successHandler, Func<Exception, Task> failureHandler)
{
try
{
// Step 1) Look up the SMO metadata
objectMetadata = metadataFactory.GetObjectMetadata(await connector(), objectName, objectType);
// Step 2) Get and execute a query for the rows in the object we're looking up
EditSessionQueryExecutionState state = await queryRunner(ConstructInitializeQuery());
if (state.Query == null)
{
// TODO: Move to SR file
string message = state.Message ?? SR.EditDataQueryFailed;
throw new Exception(message);
}
// Step 3) Setup the internal state
associatedResultSet = ValidateQueryForSession(state.Query);
NextRowId = associatedResultSet.RowCount;
EditCache = new ConcurrentDictionary<long, RowEditBase>();
IsInitialized = true;
// Step 4) Return our success
await successHandler();
}
catch (Exception e)
{
await failureHandler(e);
}
}
private async Task CommitEditsInternal(DbConnection connection, Func<Task> successHandler, Func<Exception, Task> errorHandler)
{
try
@@ -378,5 +466,50 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
await errorHandler(e);
}
}
private string ConstructInitializeQuery()
{
// Using the columns we know, put together a query for the rows in the table
var columns = objectMetadata.Columns.Select(col => col.EscapedName);
var columnClause = string.Join(", ", columns);
return $"SELECT ${columnClause} FROM ${objectMetadata.EscapedMultipartName}";
}
private void ThrowIfNotInitialized()
{
if (!IsInitialized)
{
throw new InvalidOperationException(SR.EditDataSessionNotInitialized);
}
}
/// <summary>
/// State object to return upon completion of an edit session intialization query
/// </summary>
public class EditSessionQueryExecutionState
{
/// <summary>
/// The query object that was used to execute the edit initialization query. If
/// <c>null</c> the query was not successfully executed.
/// </summary>
public Query Query { get; set; }
/// <summary>
/// Any message that may have occurred during execution of the query (ie, exceptions).
/// If this is and <see cref="Query"/> are <c>null</c> then the error messages were
/// returned via message events.
/// </summary>
public string Message { get; set; }
/// <summary>
/// Constructs a new instance. Sets the values of the properties.
/// </summary>
public EditSessionQueryExecutionState(Query query, string message = null)
{
Query = query;
Message = message;
}
}
}
}

View File

@@ -0,0 +1,85 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Linq;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
/// <summary>
/// Provides metadata about the table or view being edited
/// </summary>
public class EditTableMetadata
{
/// <summary>
/// Constructs a simple edit table metadata provider
/// </summary>
public EditTableMetadata()
{
HasExtendedProperties = false;
}
#region Basic Properties (properties provided by SMO)
/// <summary>
/// List of columns in the object being edited
/// </summary>
public EditColumnMetadata[] Columns { get; set; }
/// <summary>
/// Full escaped multipart identifier for the object being edited
/// </summary>
public string EscapedMultipartName { get; set; }
/// <summary>
/// Whether or not the object being edited is memory optimized
/// </summary>
public bool IsMemoryOptimized { get; set; }
#endregion
#region Extended Properties (properties provided by SqlClient)
/// <summary>
/// Whether or not the table has had extended properties added to it
/// </summary>
public bool HasExtendedProperties { get; private set; }
/// <summary>
/// List of columns that are used to uniquely identify a row
/// </summary>
public EditColumnMetadata[] KeyColumns { get; private set; }
#endregion
/// <summary>
/// Extracts extended column properties from the database columns from SQL Client
/// </summary>
/// <param name="dbColumnWrappers">The column information provided by SQL Client</param>
public void Extend(DbColumnWrapper[] dbColumnWrappers)
{
Validate.IsNotNull(nameof(dbColumnWrappers), dbColumnWrappers);
// Iterate over the column wrappers and improve the columns we have
for (int i = 0; i < Columns.Length; i++)
{
Columns[i].Extend(dbColumnWrappers[i]);
}
// Determine what the key columns are
KeyColumns = Columns.Where(c => c.IsKey.HasTrue()).ToArray();
if (KeyColumns.Length == 0)
{
// We didn't find any explicit key columns. Instead, we'll use all columns that are
// trustworthy for uniqueness (usually all the columns)
KeyColumns = Columns.Where(c => c.IsTrustworthyForUniqueness.HasTrue()).ToArray();
}
// Mark that the table is now extended
HasExtendedProperties = true;
}
}
}

View File

@@ -4,7 +4,6 @@
//
using System.Data.Common;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
@@ -17,10 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// Generates a edit-ready metadata object
/// </summary>
/// <param name="connection">Connection to use for getting metadata</param>
/// <param name="columns">List of columns from a query against the object</param>
/// <param name="objectName">Name of the object to return metadata for</param>
/// <param name="objectType">Type of the object to return metadata for</param>
/// <returns>Metadata about the object requested</returns>
IEditTableMetadata GetObjectMetadata(DbConnection connection, DbColumnWrapper[] columns, string objectName, string objectType);
EditTableMetadata GetObjectMetadata(DbConnection connection, string objectName, string objectType);
}
}

View File

@@ -1,36 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
/// <summary>
/// An interface used in edit scenarios that defines properties for what columns are primary
/// keys, and other metadata of the table.
/// </summary>
public interface IEditTableMetadata
{
/// <summary>
/// All columns in the table that's being edited
/// </summary>
IReadOnlyList<EditColumnWrapper> Columns { get; }
/// <summary>
/// The escaped name of the table that's being edited
/// </summary>
string EscapedMultipartName { get; }
/// <summary>
/// Whether or not this table is a memory optimized table
/// </summary>
bool IsMemoryOptimized { get; }
/// <summary>
/// Columns that can be used to uniquely identify the a row
/// </summary>
IReadOnlyList<EditColumnWrapper> KeyColumns { get; }
}
}

View File

@@ -4,12 +4,13 @@
//
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
@@ -22,11 +23,10 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
/// Generates a edit-ready metadata object using SMO
/// </summary>
/// <param name="connection">Connection to use for getting metadata</param>
/// <param name="columns">List of columns from a query against the object</param>
/// <param name="objectName">Name of the object to return metadata for</param>
/// <param name="objectType">Type of the object to return metadata for</param>
/// <returns>Metadata about the object requested</returns>
public IEditTableMetadata GetObjectMetadata(DbConnection connection, DbColumnWrapper[] columns, string objectName, string objectType)
public EditTableMetadata GetObjectMetadata(DbConnection connection, string objectName, string objectType)
{
// Get a connection to the database for SMO purposes
SqlConnection sqlConn = connection as SqlConnection;
@@ -44,25 +44,59 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
sqlConn = reliableConn.GetUnderlyingConnection();
}
// Connect with SMO and get the metadata for the table
Server server = new Server(new ServerConnection(sqlConn));
TableViewTableTypeBase result;
TableViewTableTypeBase smoResult;
switch (objectType.ToLowerInvariant())
{
case "table":
result = server.Databases[sqlConn.Database].Tables[objectName];
smoResult = server.Databases[sqlConn.Database].Tables[objectName];
break;
case "view":
result = server.Databases[sqlConn.Database].Views[objectName];
smoResult = server.Databases[sqlConn.Database].Views[objectName];
break;
default:
throw new ArgumentOutOfRangeException(nameof(objectType), SR.EditDataUnsupportedObjectType(objectType));
}
if (result == null)
if (smoResult == null)
{
throw new ArgumentOutOfRangeException(nameof(objectName), SR.EditDataObjectMetadataNotFound);
}
return new SmoEditTableMetadata(columns, result);
// Generate the edit column metadata
List<EditColumnMetadata> editColumns = new List<EditColumnMetadata>();
for (int i = 0; i < smoResult.Columns.Count; i++)
{
Column smoColumn = smoResult.Columns[i];
// The default value may be escaped
string defaultValue = smoColumn.DefaultConstraint == null
? null
: SqlScriptFormatter.UnwrapLiteral(smoColumn.DefaultConstraint.Text);
EditColumnMetadata column = new EditColumnMetadata
{
DefaultValue = defaultValue,
EscapedName = SqlScriptFormatter.FormatIdentifier(smoColumn.Name),
Ordinal = i,
};
editColumns.Add(column);
}
// Only tables can be memory-optimized
Table smoTable = smoResult as Table;
bool isMemoryOptimized = smoTable != null && smoTable.IsMemoryOptimized;
// Escape the parts of the name
string[] objectNameParts = {smoResult.Schema, smoResult.Name};
string escapedMultipartName = SqlScriptFormatter.FormatMultipartIdentifier(objectNameParts);
return new EditTableMetadata
{
Columns = editColumns.ToArray(),
EscapedMultipartName = escapedMultipartName,
IsMemoryOptimized = isMemoryOptimized,
};
}
}
}

View File

@@ -1,109 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData
{
/// <summary>
/// Provides metadata about the table or view being edited
/// </summary>
public class SmoEditTableMetadata : IEditTableMetadata
{
private readonly List<EditColumnWrapper> columns;
private readonly List<EditColumnWrapper> keyColumns;
/// <summary>
/// Constructor that extracts useful metadata from the provided metadata objects
/// </summary>
/// <param name="dbColumns">DB columns from the ResultSet</param>
/// <param name="smoObject">SMO metadata object for the table/view being edited</param>
public SmoEditTableMetadata(IList<DbColumnWrapper> dbColumns, TableViewTableTypeBase smoObject)
{
Validate.IsNotNull(nameof(dbColumns), dbColumns);
Validate.IsNotNull(nameof(smoObject), smoObject);
// Make sure that we have equal columns on both metadata providers
Debug.Assert(dbColumns.Count == smoObject.Columns.Count);
// Create the columns for edit usage
columns = new List<EditColumnWrapper>();
for (int i = 0; i < dbColumns.Count; i++)
{
Column smoColumn = smoObject.Columns[i];
DbColumnWrapper dbColumn = dbColumns[i];
// A column is trustworthy for uniqueness if it can be updated or it has an identity
// property. If both of these are false (eg, timestamp) we can't trust it to uniquely
// identify a row in the table
bool isTrustworthyForUniqueness = dbColumn.IsUpdatable || smoColumn.Identity;
// The default value may be escaped
string defaultValue = smoColumn.DefaultConstraint == null
? null
: SqlScriptFormatter.UnwrapLiteral(smoColumn.DefaultConstraint.Text);
EditColumnWrapper column = new EditColumnWrapper
{
DbColumn = dbColumn,
Ordinal = i,
DefaultValue = defaultValue,
EscapedName = SqlScriptFormatter.FormatIdentifier(dbColumn.ColumnName),
IsTrustworthyForUniqueness = isTrustworthyForUniqueness,
// A key column is determined by whether it is in the primary key and trustworthy
IsKey = smoColumn.InPrimaryKey && isTrustworthyForUniqueness,
// A column is calculated if it is identity, computed, or otherwise not updatable
IsCalculated = smoColumn.Identity || smoColumn.Computed || !dbColumn.IsUpdatable
};
columns.Add(column);
}
// Determine what the key columns are
keyColumns = columns.Where(c => c.IsKey).ToList();
if (keyColumns.Count == 0)
{
// We didn't find any explicit key columns. Instead, we'll use all columns that are
// trustworthy for uniqueness (usually all the columns)
keyColumns = columns.Where(c => c.IsTrustworthyForUniqueness).ToList();
}
// If a table is memory optimized it is Hekaton. If it's a view, then it can't be Hekaton
Table smoTable = smoObject as Table;
IsMemoryOptimized = smoTable != null && smoTable.IsMemoryOptimized;
// Escape the parts of the name
string[] objectNameParts = {smoObject.Schema, smoObject.Name};
EscapedMultipartName = SqlScriptFormatter.FormatMultipartIdentifier(objectNameParts);
}
/// <summary>
/// Read-only list of columns in the object being edited
/// </summary>
public IReadOnlyList<EditColumnWrapper> Columns => columns.AsReadOnly();
/// <summary>
/// Full escaped multipart identifier for the object being edited
/// </summary>
public string EscapedMultipartName { get; }
/// <summary>
/// Whether or not the object being edited is memory optimized
/// </summary>
public bool IsMemoryOptimized { get; }
/// <summary>
/// Read-only list of columns that are used to uniquely identify a row
/// </summary>
public IReadOnlyList<EditColumnWrapper> KeyColumns => keyColumns.AsReadOnly();
}
}

View File

@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <param name="rowId">Internal ID of the row that is being created</param>
/// <param name="associatedResultSet">The result set for the rows in the table we're editing</param>
/// <param name="associatedMetadata">The metadata for table we're editing</param>
public RowCreate(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
public RowCreate(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
: base(rowId, associatedResultSet, associatedMetadata)
{
newCells = new CellUpdate[associatedResultSet.Columns.Length];

View File

@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <param name="rowId">Internal ID of the row to be deleted</param>
/// <param name="associatedResultSet">Result set that is being edited</param>
/// <param name="associatedMetadata">Improved metadata of the object being edited</param>
public RowDelete(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
public RowDelete(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
: base(rowId, associatedResultSet, associatedMetadata)
{
}

View File

@@ -36,7 +36,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <param name="rowId">The internal ID of the row that is being edited</param>
/// <param name="associatedResultSet">The result set that will be updated</param>
/// <param name="associatedMetadata">Metadata provider for the object to edit</param>
protected RowEditBase(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
protected RowEditBase(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
{
RowId = rowId;
AssociatedResultSet = associatedResultSet;
@@ -58,7 +58,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <summary>
/// The metadata for the table this edit is associated to
/// </summary>
public IEditTableMetadata AssociatedObjectMetadata { get; }
public EditTableMetadata AssociatedObjectMetadata { get; }
/// <summary>
/// Sort ID for a row edit. Ensures that when a collection of RowEditBase objects are
@@ -162,7 +162,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
}
IList<DbCellValue> row = AssociatedResultSet.GetRow(RowId);
foreach (EditColumnWrapper col in AssociatedObjectMetadata.KeyColumns)
foreach (EditColumnMetadata col in AssociatedObjectMetadata.KeyColumns)
{
// Put together a clause for the value of the cell
DbCellValue cellData = row[col.Ordinal];

View File

@@ -39,7 +39,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <param name="rowId">Internal ID of the row that will be updated with this object</param>
/// <param name="associatedResultSet">Result set for the rows of the object to update</param>
/// <param name="associatedMetadata">Metadata provider for the object to update</param>
public RowUpdate(long rowId, ResultSet associatedResultSet, IEditTableMetadata associatedMetadata)
public RowUpdate(long rowId, ResultSet associatedResultSet, EditTableMetadata associatedMetadata)
: base(rowId, associatedResultSet, associatedMetadata)
{
cellUpdates = new ConcurrentDictionary<int, CellUpdate>();

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
@@ -27,106 +105,322 @@
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader><resheader name="version"><value>1.3</value></resheader><resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader><data name="ConnectionServiceConnectErrorNullParams"><value>Los parámetros de conexión no pueden ser nulos</value></data>
<data name="ConnectionServiceListDbErrorNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
<data name="ConnectionServiceListDbErrorNotConnected"><value>SpecifiedUri '{0}' no tiene una conexión existente</value></data>
<data name="ConnectionServiceConnStringInvalidAuthType"><value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value></data>
<data name="ConnectionServiceConnStringInvalidIntent"><value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value></data>
<data name="ConnectionServiceConnectionCanceled"><value>Conexión cancelada</value></data>
<data name="ConnectionParamsValidateNullOwnerUri"><value>OwnerUri no puede ser nulo ni estar vacío</value></data>
<data name="ConnectionParamsValidateNullConnection"><value>El objeto de detalles de conexión no puede ser nulo</value></data>
<data name="ConnectionParamsValidateNullServerName"><value>ServerName no puede ser nulo ni estar vacío</value></data>
<data name="ConnectionParamsValidateNullSqlAuth"><value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value></data>
<data name="QueryServiceCancelAlreadyCompleted"><value>Ya se ha completado la consulta, no se puede cancelar</value></data>
<data name="QueryServiceCancelDisposeFailed"><value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value></data>
<data name="QueryServiceQueryCancelled"><value>Consulta cancelada por el usuario</value></data>
<data name="QueryServiceSubsetBatchNotCompleted"><value>El lote aún no ha finalizado,</value></data>
<data name="QueryServiceSubsetBatchOutOfRange"><value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value></data>
<data name="QueryServiceSubsetResultSetOutOfRange"><value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value></data>
<data name="QueryServiceDataReaderByteCountInvalid"><value>El número máximo de bytes a devolver debe ser mayor que cero</value></data>
<data name="QueryServiceDataReaderCharCountInvalid"><value>El número máximo de caracteres a devolver debe ser mayor que cero</value></data>
<data name="QueryServiceDataReaderXmlCountInvalid"><value>El número máximo de bytes XML a devolver debe ser mayor que cero</value></data>
<data name="QueryServiceFileWrapperWriteOnly"><value>El método de acceso no puede ser de sólo escritura</value></data>
<data name="QueryServiceFileWrapperNotInitialized"><value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value></data>
<data name="QueryServiceFileWrapperReadOnly"><value>Este FileStreamWrapper no se puede utilizar para escritura.</value></data>
<data name="QueryServiceAffectedOneRow"><value>(1 fila afectada)</value></data>
<data name="QueryServiceAffectedRows"><value>({0} filas afectadas)</value></data>
<data name="QueryServiceCompletedSuccessfully"><value>Comandos finalizados correctamente.</value></data>
<data name="QueryServiceErrorFormat"><value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value></data>
<data name="QueryServiceQueryFailed"><value>Error en la consulta: {0}</value></data>
<data name="QueryServiceColumnNull"><value>(Ningún nombre de columna)</value></data>
<data name="QueryServiceRequestsNoQuery"><value>La consulta solicitada no existe</value></data>
<data name="QueryServiceQueryInvalidOwnerUri"><value>Este editor no está conectado a una base de datos</value></data>
<data name="QueryServiceQueryInProgress"><value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value></data>
<data name="QueryServiceMessageSenderNotSql"><value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value></data>
<data name="QueryServiceResultSetReaderNull"><value>Lector no puede ser nulo</value></data>
<data name="QueryServiceSaveAsResultSetNotComplete"><value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value></data>
<data name="QueryServiceSaveAsMiscStartingError"><value>Error interno al iniciar el guardado de la tarea</value></data>
<data name="QueryServiceSaveAsInProgress"><value>Una operacion de guardado en la misma ruta se encuentra en curso</value></data>
<data name="QueryServiceSaveAsFail"><value>Error al guardar {0}: {1}</value></data>
<data name="QueryServiceResultSetNotRead"><value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value></data>
<data name="QueryServiceResultSetStartRowOutOfRange"><value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value></data>
<data name="QueryServiceResultSetRowCountOutOfRange"><value>La cantidad de filas debe ser un entero positivo</value></data>
<data name="QueryServiceResultSetNoColumnSchema"><value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value></data>
<data name="QueryServiceExecutionPlanNotFound"><value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value></data>
<data name="PeekDefinitionAzureError"><value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value></data>
<data name="PeekDefinitionError"><value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value></data>
<data name="PeekDefinitionNoResultsError"><value>No se encontraron resultados.</value></data>
<data name="PeekDefinitionDatabaseError"><value>No se pudo obtener ningún objeto asociado a la base de datos.</value></data>
<data name="PeekDefinitionNotConnectedError"><value>Conéctese a un servidor.</value></data>
<data name="PeekDefinitionTimedoutError"><value>Tiempo de espera agotado para esta operación.</value></data>
<data name="PeekDefinitionTypeNotSupportedError"><value>Esta característica no admite actualmente este tipo de objeto.</value></data>
<data name="WorkspaceServicePositionLineOutOfRange"><value>Posición está fuera del intervalo de la línea de archivo</value></data>
<data name="WorkspaceServicePositionColumnOutOfRange"><value>Posición está fuera del intervalo de la columna de la línea {0}</value></data>
<data name="WorkspaceServiceBufferPositionOutOfOrder"><value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value></data>
<data name="EE_BatchSqlMessageNoProcedureInfo"><value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value></data>
<data name="EE_BatchSqlMessageWithProcedureInfo"><value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value></data>
<data name="EE_BatchSqlMessageNoLineInfo"><value>Msg {0}, nivel {1}, {2} de estado</value></data>
<data name="EE_BatchError_Exception"><value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value></data>
<data name="EE_BatchExecutionInfo_RowsAffected"><value>({0} filas afectadas)</value></data>
<data name="EE_ExecutionNotYetCompleteError"><value>La ejecución anterior aún no está completa.</value></data>
<data name="EE_ScriptError_Error"><value>Se ha producido un error de secuencias de comandos.</value></data>
<data name="EE_ScriptError_ParsingSyntax"><value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value></data>
<data name="EE_ScriptError_FatalError"><value>Se ha producido un error grave.</value></data>
<data name="EE_ExecutionInfo_FinalizingLoop"><value>La ejecución completó {0} veces...</value></data>
<data name="EE_ExecutionInfo_QueryCancelledbyUser"><value>Se canceló la consulta.</value></data>
<data name="EE_BatchExecutionError_Halting"><value>Se produjo un error mientras se ejecutaba el lote.</value></data>
<data name="EE_BatchExecutionError_Ignoring"><value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value></data>
<data name="EE_ExecutionInfo_InitilizingLoop"><value>Iniciando bucle de ejecución de {0} veces...</value></data>
<data name="EE_ExecutionError_CommandNotSupported"><value>No se admite el comando {0}.</value></data>
<data name="EE_ExecutionError_VariableNotFound"><value>La variable {0} no se encontró.</value></data>
<data name="BatchParserWrapperExecutionEngineError"><value>Error de ejecución de SQL: {0}</value></data>
<data name="BatchParserWrapperExecutionError"><value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value></data>
<data name="BatchParserWrapperExecutionEngineBatchMessage"><value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value></data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing"><value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value></data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished"><value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value></data>
<data name="BatchParserWrapperExecutionEngineBatchCancelling"><value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value></data>
<data name="EE_ScriptError_Warning"><value>Advertencia de scripting.</value></data>
<data name="TroubleshootingAssistanceMessage"><value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value></data>
<data name="BatchParser_CircularReference"><value>El archivo '{0}' se incluyó recursivamente.</value></data>
<data name="BatchParser_CommentNotTerminated"><value>Falta la marca de final de comentario ' * /'.</value></data>
<data name="BatchParser_StringNotTerminated"><value>Sin comilla de cierre después de la cadena de caracteres.</value></data>
<data name="BatchParser_IncorrectSyntax"><value>Se encontró sintaxis incorrecta al analizar '{0}'.</value></data>
<data name="BatchParser_VariableNotDefined"><value>La variable {0} no está definida.</value></data>
<data name="TestLocalizationConstant"><value>prueba</value></data>
<data name="ErrorUnexpectedCodeObjectType"><value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value></data>
<data name="ErrorEmptyStringReplacement"><value>Sustitución de una cadena vacía por una cadena vacía.</value></data>
<data name="EditDataSessionNotFound"><value>Sesión de edición no existe,</value></data>
<data name="EditDataQueryNotCompleted"><value>La consulta no ha finalizado.</value></data>
<data name="EditDataQueryImproperResultSets"><value>La consulta no generó un único set de resultados</value></data>
<data name="EditDataFailedAddRow"><value>Falló al agregar una nueva fila a la caché de actualización</value></data>
<data name="EditDataRowOutOfRange"><value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value></data>
<data name="EditDataUpdatePending"><value>Una actualización está pendiente para esta fila y debe de revertirse primero</value></data>
<data name="EditDataUpdateNotPending"><value>El ID de la fila ingresado no tiene actualizaciones pendientes</value></data>
<data name="EditDataObjectMetadataNotFound"><value>La metadata de la tabla o vista no pudo ser encontrada</value></data>
<data name="EditDataInvalidFormatBinary"><value>Formato inválido para columna binaria</value></data>
<data name="EditDataInvalidFormatBoolean"><value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value></data>
<data name="EditDataCreateScriptMissingValue"><value>Falta un valor requerido de la celda</value></data>
<data name="EditDataDeleteSetCell"><value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value></data>
<data name="EditDataColumnIdOutOfRange"><value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value></data>
<data name="EditDataColumnCannotBeEdited"><value>La columna no puede ser editada</value></data>
<data name="EditDataColumnNoKeyColumns"><value>No se encontró ninguna columna clave</value></data>
<data name="EditDataScriptFilePathNull"><value>Proporcione un nombre de archivo de salida</value></data>
<data name="EditDataUnsupportedObjectType"><value>Objeto de base de datos {0} no puede ser usado para modificación.</value></data>
<data name="ConnectionServiceDbErrorDefaultNotConnected"><value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value></data>
</root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
<value>Los parámetros de conexión no pueden ser nulos</value>
</data>
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene una conexión existente</value>
</data>
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
<value>El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'.</value>
</data>
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
<value>El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'.</value>
</data>
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
<value>Conexión cancelada</value>
</data>
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
<value>OwnerUri no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
<value>El objeto de detalles de conexión no puede ser nulo</value>
</data>
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
<value>ServerName no puede ser nulo ni estar vacío</value>
</data>
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
<value>{0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin</value>
</data>
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
<value>Ya se ha completado la consulta, no se puede cancelar</value>
</data>
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
<value>La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario.</value>
</data>
<data name="QueryServiceQueryCancelled" xml:space="preserve">
<value>Consulta cancelada por el usuario</value>
</data>
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
<value>El lote aún no ha finalizado,</value>
</data>
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
<value>Índice de lote no puede ser menor que 0 o mayor que el número de lotes</value>
</data>
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
<value>Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados</value>
</data>
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
<value>El número máximo de bytes a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
<value>El número máximo de caracteres a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
<value>El número máximo de bytes XML a devolver debe ser mayor que cero</value>
</data>
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
<value>El método de acceso no puede ser de sólo escritura</value>
</data>
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
<value>FileStreamWrapper debe inicializarse antes de realizar operaciones</value>
</data>
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
<value>Este FileStreamWrapper no se puede utilizar para escritura.</value>
</data>
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
<value>(1 fila afectada)</value>
</data>
<data name="QueryServiceAffectedRows" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
<value>Comandos finalizados correctamente.</value>
</data>
<data name="QueryServiceErrorFormat" xml:space="preserve">
<value>Msg {0}, nivel {1} estado {2}, línea {3} {4} {5}</value>
</data>
<data name="QueryServiceQueryFailed" xml:space="preserve">
<value>Error en la consulta: {0}</value>
</data>
<data name="QueryServiceColumnNull" xml:space="preserve">
<value>(Ningún nombre de columna)</value>
</data>
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
<value>La consulta solicitada no existe</value>
</data>
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
<value>Este editor no está conectado a una base de datos</value>
</data>
<data name="QueryServiceQueryInProgress" xml:space="preserve">
<value>Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización.</value>
</data>
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
<value>Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection</value>
</data>
<data name="QueryServiceResultSetReaderNull" xml:space="preserve">
<value>Lector no puede ser nulo</value>
</data>
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
<value>No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta</value>
</data>
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
<value>Error interno al iniciar el guardado de la tarea</value>
</data>
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
<value>Una operacion de guardado en la misma ruta se encuentra en curso</value>
</data>
<data name="QueryServiceSaveAsFail" xml:space="preserve">
<value>Error al guardar {0}: {1}</value>
</data>
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
<value>No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor</value>
</data>
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
<value>Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados</value>
</data>
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
<value>La cantidad de filas debe ser un entero positivo</value>
</data>
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
<value>No se pudo recuperar el esquema de columna para el conjunto de resultados</value>
</data>
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
<value>No se pudo recuperar un plan de ejecución del conjunto de resultados</value>
</data>
<data name="PeekDefinitionAzureError" xml:space="preserve">
<value>Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0}</value>
</data>
<data name="PeekDefinitionError" xml:space="preserve">
<value>Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0}</value>
</data>
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
<value>No se encontraron resultados.</value>
</data>
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
<value>No se pudo obtener ningún objeto asociado a la base de datos.</value>
</data>
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
<value>Conéctese a un servidor.</value>
</data>
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
<value>Tiempo de espera agotado para esta operación.</value>
</data>
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
<value>Esta característica no admite actualmente este tipo de objeto.</value>
</data>
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la línea de archivo</value>
</data>
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
<value>Posición está fuera del intervalo de la columna de la línea {0}</value>
</data>
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
<value>Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3})</value>
</data>
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
<value>Msg {0}, {1}, nivel de estado {2}, línea {3}</value>
</data>
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
<value>Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4}</value>
</data>
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
<value>Msg {0}, nivel {1}, {2} de estado</value>
</data>
<data name="EE_BatchError_Exception" xml:space="preserve">
<value>Se produjo un error al procesar el lote. Mensaje de error: {0}</value>
</data>
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
<value>({0} filas afectadas)</value>
</data>
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
<value>La ejecución anterior aún no está completa.</value>
</data>
<data name="EE_ScriptError_Error" xml:space="preserve">
<value>Se ha producido un error de secuencias de comandos.</value>
</data>
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta mientras se estaba analizando {0}.</value>
</data>
<data name="EE_ScriptError_FatalError" xml:space="preserve">
<value>Se ha producido un error grave.</value>
</data>
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
<value>La ejecución completó {0} veces...</value>
</data>
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
<value>Se canceló la consulta.</value>
</data>
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote.</value>
</data>
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
<value>Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error.</value>
</data>
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
<value>Iniciando bucle de ejecución de {0} veces...</value>
</data>
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
<value>No se admite el comando {0}.</value>
</data>
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
<value>La variable {0} no se encontró.</value>
</data>
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
<value>Error de ejecución de SQL: {0}</value>
</data>
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
<value>Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
<value>Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
<value>Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
<value>Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes.</value>
</data>
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
<value>Cancelando la ejecución por lotes del contenedor del analizador por lotes.</value>
</data>
<data name="EE_ScriptError_Warning" xml:space="preserve">
<value>Advertencia de scripting.</value>
</data>
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
<value>Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto.</value>
</data>
<data name="BatchParser_CircularReference" xml:space="preserve">
<value>El archivo '{0}' se incluyó recursivamente.</value>
</data>
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
<value>Falta la marca de final de comentario ' * /'.</value>
</data>
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
<value>Sin comilla de cierre después de la cadena de caracteres.</value>
</data>
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
<value>Se encontró sintaxis incorrecta al analizar '{0}'.</value>
</data>
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
<value>La variable {0} no está definida.</value>
</data>
<data name="TestLocalizationConstant" xml:space="preserve">
<value>prueba</value>
</data>
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
<value>No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1}</value>
</data>
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
<value>Sustitución de una cadena vacía por una cadena vacía.</value>
</data>
<data name="EditDataSessionNotFound" xml:space="preserve">
<value>Sesión de edición no existe,</value>
</data>
<data name="EditDataQueryNotCompleted" xml:space="preserve">
<value>La consulta no ha finalizado.</value>
</data>
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
<value>La consulta no generó un único set de resultados</value>
</data>
<data name="EditDataFailedAddRow" xml:space="preserve">
<value>Falló al agregar una nueva fila a la caché de actualización</value>
</data>
<data name="EditDataRowOutOfRange" xml:space="preserve">
<value>El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición</value>
</data>
<data name="EditDataUpdatePending" xml:space="preserve">
<value>Una actualización está pendiente para esta fila y debe de revertirse primero</value>
</data>
<data name="EditDataUpdateNotPending" xml:space="preserve">
<value>El ID de la fila ingresado no tiene actualizaciones pendientes</value>
</data>
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
<value>La metadata de la tabla o vista no pudo ser encontrada</value>
</data>
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
<value>Formato inválido para columna binaria</value>
</data>
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
<value>Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false</value>
</data>
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
<value>Falta un valor requerido de la celda</value>
</data>
<data name="EditDataDeleteSetCell" xml:space="preserve">
<value>Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada.</value>
</data>
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
<value>El ID de la columna debe de estar en el rango de columnas de la consulta.</value>
</data>
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
<value>La columna no puede ser editada</value>
</data>
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
<value>No se encontró ninguna columna clave</value>
</data>
<data name="EditDataScriptFilePathNull" xml:space="preserve">
<value>Proporcione un nombre de archivo de salida</value>
</data>
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
<value>Objeto de base de datos {0} no puede ser usado para modificación.</value>
</data>
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' no tiene alguna conexión por defecto</value>
</data>
</root>

View File

@@ -120,451 +120,475 @@
<data name="ConnectionServiceConnectErrorNullParams" xml:space="preserve">
<value>Connection parameters cannot be null</value>
<comment></comment>
</data>
</data>
<data name="ConnectionServiceListDbErrorNullOwnerUri" xml:space="preserve">
<value>OwnerUri cannot be null or empty</value>
<comment></comment>
</data>
</data>
<data name="ConnectionServiceListDbErrorNotConnected" xml:space="preserve">
<value>SpecifiedUri '{0}' does not have existing connection</value>
<comment>.
Parameters: 0 - uri (string) </comment>
</data>
</data>
<data name="ConnectionServiceDbErrorDefaultNotConnected" xml:space="preserve">
<value>Specified URI '{0}' does not have a default connection</value>
<comment>.
Parameters: 0 - uri (string) </comment>
</data>
</data>
<data name="ConnectionServiceConnStringInvalidAuthType" xml:space="preserve">
<value>Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.</value>
<comment>.
Parameters: 0 - authType (string) </comment>
</data>
</data>
<data name="ConnectionServiceConnStringInvalidIntent" xml:space="preserve">
<value>Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.</value>
<comment>.
Parameters: 0 - intent (string) </comment>
</data>
</data>
<data name="ConnectionServiceConnectionCanceled" xml:space="preserve">
<value>Connection canceled</value>
<comment></comment>
</data>
</data>
<data name="ConnectionParamsValidateNullOwnerUri" xml:space="preserve">
<value>OwnerUri cannot be null or empty</value>
<comment></comment>
</data>
</data>
<data name="ConnectionParamsValidateNullConnection" xml:space="preserve">
<value>Connection details object cannot be null</value>
<comment></comment>
</data>
</data>
<data name="ConnectionParamsValidateNullServerName" xml:space="preserve">
<value>ServerName cannot be null or empty</value>
<comment></comment>
</data>
</data>
<data name="ConnectionParamsValidateNullSqlAuth" xml:space="preserve">
<value>{0} cannot be null or empty when using SqlLogin authentication</value>
<comment>.
Parameters: 0 - component (string) </comment>
</data>
</data>
<data name="ErrorUnexpectedCodeObjectType" xml:space="preserve">
<value>Cannot convert SqlCodeObject Type {0} to Type {1}</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceCancelAlreadyCompleted" xml:space="preserve">
<value>The query has already completed, it cannot be cancelled</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceCancelDisposeFailed" xml:space="preserve">
<value>Query successfully cancelled, failed to dispose query. Owner URI not found.</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceQueryCancelled" xml:space="preserve">
<value>Query was canceled by user</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSubsetBatchNotCompleted" xml:space="preserve">
<value>The batch has not completed, yet</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSubsetBatchOutOfRange" xml:space="preserve">
<value>Batch index cannot be less than 0 or greater than the number of batches</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSubsetResultSetOutOfRange" xml:space="preserve">
<value>Result set index cannot be less than 0 or greater than the number of result sets</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceDataReaderByteCountInvalid" xml:space="preserve">
<value>Maximum number of bytes to return must be greater than zero</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceDataReaderCharCountInvalid" xml:space="preserve">
<value>Maximum number of chars to return must be greater than zero</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceDataReaderXmlCountInvalid" xml:space="preserve">
<value>Maximum number of XML bytes to return must be greater than zero</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceFileWrapperWriteOnly" xml:space="preserve">
<value>Access method cannot be write-only</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceFileWrapperNotInitialized" xml:space="preserve">
<value>FileStreamWrapper must be initialized before performing operations</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceFileWrapperReadOnly" xml:space="preserve">
<value>This FileStreamWrapper cannot be used for writing</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceAffectedOneRow" xml:space="preserve">
<value>(1 row affected)</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceAffectedRows" xml:space="preserve">
<value>({0} rows affected)</value>
<comment>.
Parameters: 0 - rows (long) </comment>
</data>
</data>
<data name="QueryServiceCompletedSuccessfully" xml:space="preserve">
<value>Commands completed successfully.</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceErrorFormat" xml:space="preserve">
<value>Msg {0}, Level {1}, State {2}, Line {3}{4}{5}</value>
<comment>.
Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) </comment>
</data>
</data>
<data name="QueryServiceQueryFailed" xml:space="preserve">
<value>Query failed: {0}</value>
<comment>.
Parameters: 0 - message (string) </comment>
</data>
</data>
<data name="QueryServiceColumnNull" xml:space="preserve">
<value>(No column name)</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceRequestsNoQuery" xml:space="preserve">
<value>The requested query does not exist</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceQueryInvalidOwnerUri" xml:space="preserve">
<value>This editor is not connected to a database</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceQueryInProgress" xml:space="preserve">
<value>A query is already in progress for this editor session. Please cancel this query or wait for its completion.</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceMessageSenderNotSql" xml:space="preserve">
<value>Sender for OnInfoMessage event must be a SqlConnection</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceResultSetAddNoRows" xml:space="preserve">
<value>Cannot add row to result buffer, data reader does not contain rows</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSaveAsResultSetNotComplete" xml:space="preserve">
<value>Result cannot be saved until query execution has completed</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSaveAsMiscStartingError" xml:space="preserve">
<value>Internal error occurred while starting save task</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSaveAsInProgress" xml:space="preserve">
<value>A save request to the same path is in progress</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceSaveAsFail" xml:space="preserve">
<value>Failed to save {0}: {1}</value>
<comment>.
Parameters: 0 - fileName (string), 1 - message (string) </comment>
</data>
</data>
<data name="QueryServiceResultSetNotRead" xml:space="preserve">
<value>Cannot read subset unless the results have been read from the server</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceResultSetStartRowOutOfRange" xml:space="preserve">
<value>Start row cannot be less than 0 or greater than the number of rows in the result set</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceResultSetRowCountOutOfRange" xml:space="preserve">
<value>Row count must be a positive integer</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceResultSetNoColumnSchema" xml:space="preserve">
<value>Could not retrieve column schema for result set</value>
<comment></comment>
</data>
</data>
<data name="QueryServiceExecutionPlanNotFound" xml:space="preserve">
<value>Could not retrieve an execution plan from the result set </value>
<comment></comment>
</data>
</data>
<data name="PeekDefinitionAzureError" xml:space="preserve">
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
<comment>.
Parameters: 0 - errorMessage (string) </comment>
</data>
</data>
<data name="PeekDefinitionError" xml:space="preserve">
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
<comment>.
Parameters: 0 - errorMessage (string) </comment>
</data>
</data>
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
<value>No results were found.</value>
<comment></comment>
</data>
</data>
<data name="PeekDefinitionDatabaseError" xml:space="preserve">
<value>No database object was retrieved.</value>
<comment></comment>
</data>
</data>
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
<value>Please connect to a server.</value>
<comment></comment>
</data>
</data>
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
<value>Operation timed out.</value>
<comment></comment>
</data>
</data>
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
<value>This object type is currently not supported by this feature.</value>
<comment></comment>
</data>
</data>
<data name="ErrorEmptyStringReplacement" xml:space="preserve">
<value>Replacement of an empty string by an empty string.</value>
<comment></comment>
</data>
</data>
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
<value>Position is outside of file line range</value>
<comment></comment>
</data>
</data>
<data name="WorkspaceServicePositionColumnOutOfRange" xml:space="preserve">
<value>Position is outside of column range for line {0}</value>
<comment>.
Parameters: 0 - line (int) </comment>
</data>
</data>
<data name="WorkspaceServiceBufferPositionOutOfOrder" xml:space="preserve">
<value>Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3})</value>
<comment>.
Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) </comment>
</data>
</data>
<data name="EditDataObjectNotFound" xml:space="preserve">
<value>Table or view requested for edit could not be found</value>
<comment></comment>
</data>
<data name="EditDataSessionNotFound" xml:space="preserve">
<value>Edit session does not exist.</value>
<comment></comment>
</data>
</data>
<data name="EditDataSessionAlreadyExists" xml:space="preserve">
<value>Edit session already exists.</value>
<comment></comment>
</data>
<data name="EditDataSessionNotInitialized" xml:space="preserve">
<value>Edit session has not been initialized</value>
<comment></comment>
</data>
<data name="EditDataSessionAlreadyInitialized" xml:space="preserve">
<value>Edit session has already been initialized</value>
<comment></comment>
</data>
<data name="EditDataSessionAlreadyInitializing" xml:space="preserve">
<value>Edit session has already been initialized or is in the process of initializing</value>
<comment></comment>
</data>
<data name="EditDataUnsupportedObjectType" xml:space="preserve">
<value>Database object {0} cannot be used for editing.</value>
<comment>.
Parameters: 0 - typeName (string) </comment>
</data>
</data>
<data name="EditDataQueryFailed" xml:space="preserve">
<value>Query execution failed, see messages for details</value>
<comment></comment>
</data>
<data name="EditDataQueryNotCompleted" xml:space="preserve">
<value>Query has not completed execution</value>
<comment></comment>
</data>
</data>
<data name="EditDataQueryImproperResultSets" xml:space="preserve">
<value>Query did not generate exactly one result set</value>
<comment></comment>
</data>
</data>
<data name="EditDataFailedAddRow" xml:space="preserve">
<value>Failed to add new row to update cache</value>
<comment></comment>
</data>
</data>
<data name="EditDataRowOutOfRange" xml:space="preserve">
<value>Given row ID is outside the range of rows in the edit cache</value>
<comment></comment>
</data>
</data>
<data name="EditDataUpdatePending" xml:space="preserve">
<value>An update is already pending for this row and must be reverted first</value>
<comment></comment>
</data>
</data>
<data name="EditDataUpdateNotPending" xml:space="preserve">
<value>Given row ID does not have pending update</value>
<comment></comment>
</data>
</data>
<data name="EditDataColumnUpdateNotPending" xml:space="preserve">
<value>Give column ID does not have pending update</value>
<comment></comment>
</data>
</data>
<data name="EditDataObjectMetadataNotFound" xml:space="preserve">
<value>Table or view metadata could not be found</value>
<comment></comment>
</data>
</data>
<data name="EditDataInvalidFormatBinary" xml:space="preserve">
<value>Invalid format for binary column</value>
<comment></comment>
</data>
</data>
<data name="EditDataInvalidFormatBoolean" xml:space="preserve">
<value>Allowed values for boolean columns are 0, 1, "true", or "false"</value>
<comment></comment>
</data>
</data>
<data name="EditDataCreateScriptMissingValue" xml:space="preserve">
<value>A required cell value is missing</value>
<comment></comment>
</data>
</data>
<data name="EditDataDeleteSetCell" xml:space="preserve">
<value>A delete is pending for this row, a cell update cannot be applied.</value>
<comment></comment>
</data>
</data>
<data name="EditDataColumnIdOutOfRange" xml:space="preserve">
<value>Column ID must be in the range of columns for the query</value>
<comment></comment>
</data>
</data>
<data name="EditDataColumnCannotBeEdited" xml:space="preserve">
<value>Column cannot be edited</value>
<comment></comment>
</data>
</data>
<data name="EditDataColumnNoKeyColumns" xml:space="preserve">
<value>No key columns were found</value>
<comment></comment>
</data>
</data>
<data name="EditDataScriptFilePathNull" xml:space="preserve">
<value>An output filename must be provided</value>
<comment></comment>
</data>
</data>
<data name="EditDataCommitInProgress" xml:space="preserve">
<value>A commit task is in progress. Please wait for completion.</value>
<comment></comment>
</data>
</data>
<data name="EditDataComputedColumnPlaceholder" xml:space="preserve">
<value>&lt;TBD&gt;</value>
<comment></comment>
</data>
</data>
<data name="EditDataInitializeInProgress" xml:space="preserve">
<value>Another edit data initialize is in progress for this owner URI. Please wait for completion.</value>
<comment></comment>
</data>
</data>
<data name="EditDataTimeOver24Hrs" xml:space="preserve">
<value>TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999</value>
<comment></comment>
</data>
</data>
<data name="EditDataNullNotAllowed" xml:space="preserve">
<value>NULL is not allowed for this column</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchSqlMessageNoProcedureInfo" xml:space="preserve">
<value>Msg {0}, Level {1}, State {2}, Line {3}</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchSqlMessageWithProcedureInfo" xml:space="preserve">
<value>Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4}</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchSqlMessageNoLineInfo" xml:space="preserve">
<value>Msg {0}, Level {1}, State {2}</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchError_Exception" xml:space="preserve">
<value>An error occurred while the batch was being processed. The error message is: {0}</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchExecutionInfo_RowsAffected" xml:space="preserve">
<value>({0} row(s) affected)</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionNotYetCompleteError" xml:space="preserve">
<value>The previous execution is not yet complete.</value>
<comment></comment>
</data>
</data>
<data name="EE_ScriptError_Error" xml:space="preserve">
<value>A scripting error occurred.</value>
<comment></comment>
</data>
</data>
<data name="EE_ScriptError_ParsingSyntax" xml:space="preserve">
<value>Incorrect syntax was encountered while {0} was being parsed.</value>
<comment></comment>
</data>
</data>
<data name="EE_ScriptError_FatalError" xml:space="preserve">
<value>A fatal error occurred.</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionInfo_FinalizingLoop" xml:space="preserve">
<value>Execution completed {0} times...</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionInfo_QueryCancelledbyUser" xml:space="preserve">
<value>You cancelled the query.</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchExecutionError_Halting" xml:space="preserve">
<value>An error occurred while the batch was being executed.</value>
<comment></comment>
</data>
</data>
<data name="EE_BatchExecutionError_Ignoring" xml:space="preserve">
<value>An error occurred while the batch was being executed, but the error has been ignored.</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionInfo_InitilizingLoop" xml:space="preserve">
<value>Starting execution loop of {0} times...</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionError_CommandNotSupported" xml:space="preserve">
<value>Command {0} is not supported.</value>
<comment></comment>
</data>
</data>
<data name="EE_ExecutionError_VariableNotFound" xml:space="preserve">
<value>The variable {0} could not be found.</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionEngineError" xml:space="preserve">
<value>SQL Execution error: {0}</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionError" xml:space="preserve">
<value>Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3}</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionEngineBatchMessage" xml:space="preserve">
<value>Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1}</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetProcessing" xml:space="preserve">
<value>Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1}</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionEngineBatchResultSetFinished" xml:space="preserve">
<value>Batch parser wrapper execution engine batch ResultSet finished.</value>
<comment></comment>
</data>
</data>
<data name="BatchParserWrapperExecutionEngineBatchCancelling" xml:space="preserve">
<value>Canceling batch parser wrapper batch execution.</value>
<comment></comment>
</data>
</data>
<data name="EE_ScriptError_Warning" xml:space="preserve">
<value>Scripting warning.</value>
<comment></comment>
</data>
</data>
<data name="TroubleshootingAssistanceMessage" xml:space="preserve">
<value>For more information about this error, see the troubleshooting topics in the product documentation.</value>
<comment></comment>
</data>
</data>
<data name="BatchParser_CircularReference" xml:space="preserve">
<value>File '{0}' recursively included.</value>
<comment></comment>
</data>
</data>
<data name="BatchParser_CommentNotTerminated" xml:space="preserve">
<value>Missing end comment mark '*/'.</value>
<comment></comment>
</data>
</data>
<data name="BatchParser_StringNotTerminated" xml:space="preserve">
<value>Unclosed quotation mark after the character string.</value>
<comment></comment>
</data>
</data>
<data name="BatchParser_IncorrectSyntax" xml:space="preserve">
<value>Incorrect syntax was encountered while parsing '{0}'.</value>
<comment></comment>
</data>
</data>
<data name="BatchParser_VariableNotDefined" xml:space="preserve">
<value>Variable {0} is not defined.</value>
<comment></comment>
</data>
</data>
<data name="TestLocalizationConstant" xml:space="preserve">
<value>EN_LOCALIZATION</value>
<comment></comment>
</data>
</data>
<data name="SqlScriptFormatterDecimalMissingPrecision" xml:space="preserve">
<value>Decimal column is missing numeric precision or numeric scale</value>
<comment></comment>
</data>
</root>
</data>
</root>

View File

@@ -164,10 +164,22 @@ WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCo
############################################################################
# Edit Data Service
EditDataObjectNotFound = Table or view requested for edit could not be found
EditDataSessionNotFound = Edit session does not exist.
EditDataSessionAlreadyExists = Edit session already exists.
EditDataSessionNotInitialized = Edit session has not been initialized
EditDataSessionAlreadyInitialized = Edit session has already been initialized
EditDataSessionAlreadyInitializing = Edit session has already been initialized or is in the process of initializing
EditDataUnsupportedObjectType(string typeName) = Database object {0} cannot be used for editing.
EditDataQueryFailed = Query execution failed, see messages for details
EditDataQueryNotCompleted = Query has not completed execution
EditDataQueryImproperResultSets = Query did not generate exactly one result set

View File

@@ -561,6 +561,36 @@
<target state="new">NULL is not allowed for this column</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataObjectNotFound">
<source>Table or view requested for edit could not be found</source>
<target state="new">Table or view requested to edit could not be found</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataSessionAlreadyExists">
<source>Edit session already exists.</source>
<target state="new">Edit session already exists.</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataSessionNotInitialized">
<source>Edit session has not been initialized</source>
<target state="new">Edit session has not been initialized</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataSessionAlreadyInitialized">
<source>Edit session has already been initialized</source>
<target state="new">Edit session has already been initialized</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataSessionAlreadyInitializing">
<source>Edit session has already been initialized or is in the process of initializing</source>
<target state="new">Edit session has already been initialized or is in the process of initializing</target>
<note></note>
</trans-unit>
<trans-unit id="EditDataQueryFailed">
<source>Query execution failed, see messages for details</source>
<target state="new">Query execution failed, see messages for details</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -29,7 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", "");
AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function");
AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function");
}
}
/// <summary>
/// Script a Table using SMO
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a View using SMO
@@ -71,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a StoredProcedure using SMO
@@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a UserDefinedDataType using SMO
@@ -113,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a UserDefinedTableType using SMO
@@ -134,7 +134,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a Synonym using SMO
@@ -155,7 +155,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a ScalarValuedFunction using SMO
@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message);
return null;
}
}
}
/// <summary>
/// Script a TableValuedFunction using SMO
@@ -197,7 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message);
return null;
}
}
}
}
}