Я считаю, что этот сценарий может помочь вам:
DECLARE @Query TABLE (SchemaName VARCHAR(100)
,TableName VARCHAR(100)
,ColumnName VARCHAR(1000)
)
INSERT INTO @Query
SELECT A.TABLE_SCHEMA,A.TABLE_NAME,' MAX(CASE Charindex(''.'',' + QUOTENAME(COLUMN_NAME) + ')
WHEN 0 THEN 0
ELSE Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + QUOTENAME(COLUMN_NAME) + ', 128) ) AS FLOAT) AS BIGINT))
END) AS ['+COLUMN_NAME+'_MAX_LENGTH]'
FROM INFORMATION_SCHEMA.COLUMNS A
INNER JOIN INFORMATION_SCHEMA.TABLES B
ON A.TABLE_NAME = B.TABLE_NAME
WHERE TABLE_TYPE = 'BASE TABLE'
AND DATA_TYPE = 'FLOAT'
SELECT 'SELECT '+
STUFF((
SELECT ',' + ColumnName
FROM @Query Q2
WHERE Q1.SchemaName=q2.SchemaName AND Q1.TableName=q2.TableName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 2, '')
+' FROM '+Q1.SchemaName+'.'+Q1.TableName
FROM
(SELECT DISTINCT SchemaName,TableName FROM @Query) Q1
Нет Вы не были должны.
Поскольку Вы никогда не должны называть метод на другом объекте в финализаторе, он, возможно, был завершен перед Вашим объектом.
Финализатор Вашего TcpClient назовет сборщик "мусора", таким образом позвольте ему сделать.
Шаблон в Располагает:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources (here your TcpClient)
}
// dispose your unmanaged resources
// handles etc using static interop methods.
}
Нет Вы не были должны.
Из этого превосходного сообщения:
Завершение существенно отличается от окончания времени жизни объекта. С точки зрения правильности нет никакого упорядочивания между финализаторами (за пределами особого случая для критических финализаторов), поэтому если у Вас есть два объекта, что GC думает, мертвы одновременно, Вы не можете предсказать, какой финализатор завершится сначала. Это означает, что у Вас не может быть финализатора, который взаимодействует с любыми finalizable объектами, хранившими в переменных экземпляра.
Это - моя ссылочная реализация доступного/завершенного шаблона с комментариями, объясняющими, когда использовать что:
/// <summary>
/// Example of how to implement the dispose pattern.
/// </summary>
public class PerfectDisposableClass : IDisposable
{
/// <summary>
/// Type constructor.
/// </summary>
public PerfectDisposableClass()
{
Console.WriteLine( "Constructing" );
}
/// <summary>
/// Dispose method, disposes resources and suppresses finalization.
/// </summary>
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes resources used by class.
/// </summary>
/// <param name="disposing">
/// True if called from user code, false if called from finalizer.
/// When true will also call dispose for any managed objects.
/// </param>
protected virtual void Dispose(bool disposing)
{
Console.WriteLine( "Dispose(bool disposing) called, disposing = {0}", disposing );
if (disposing)
{
// Call dispose here for any managed objects (use lock if thread safety required), e.g.
//
// if( myManagedObject != null )
// {
// myManagedObject.Dispose();
// myManagedObject = null;
// }
}
}
/// <summary>
/// Called by the finalizer. Note that if <see cref="Dispose()"/> has been called then finalization will
/// have been suspended and therefore never called.
/// </summary>
/// <remarks>
/// This is a safety net to ensure that our resources (managed and unmanaged) are cleaned up after usage as
/// we can guarantee that the finalizer will be called at some point providing <see cref="Dispose()"/> is
/// not called.
/// Adding a finalizer, however, IS EXPENSIVE. So only add if using unmanaged resources (and even then try
/// and avoid a finalizer by using <see cref="SafeHandle"/>).
/// </remarks>
~PerfectDisposableClass()
{
Dispose(false);
}
}
Нет Вы не имеете к. TcpClient является классом обертки вокруг неуправляемого сокета, и там для него управляется путем, он должен быть расположен. То, что Вы сделали, достаточно.
Да Вы должны - Microsoft даже рекомендует это.
Просто помните, что код пояса-и-подтяжек никогда не звонил Вам в офис в 2:00 :)