2010-03-21 1 views
7

Qualcuno può mostrarmi un modo per convertire i tipi di dati di SQL Server (ad esempio varchar) in .Net data-types (String per esempio). Suppongo che la conversione automatica non sia possibile? Ho un oggetto 'EntityProperty' e vorrei avere una proprietà 'Type' appropriata (stringa, decimale, int32 ecc.), Al momento questa proprietà è solo una stringa - 'int32' per esempio.Come posso convertire in modo programmatico i tipi di dati SQL in tipi di dati .Net?

Un po 'di background: sto utilizzando SQL DMO in un'app interna di generazione di codice per interrogare un database e generare un DAL basato su stored procedure basato sul database. Essendo un'app interna posso prendere alcune scorciatoie e fare alcune ipotesi. Per far funzionare l'app al momento questa conversione del tipo di dati è gestita da un'istruzione Select Case che converte i tipi in stringhe e genera un insieme di proprietà basato su queste stringhe, ma preferirei un po 'più di flessibilità nel riuscire a gestire i tipi (uso di TypeOf ecc.).

Chiunque ha lavorato su qualcosa di simile?

Conosco EF, nibernato, Subsonic ecc. Potrei fare tutto questo per me, ma in questo caso, per vari motivi, devo eseguire il rollover. :)

+0

@Simon: la perdita delle risposte non è correlata; c'è stato un cambiamento a livello di sito nel sistema di rep con un ricalcolo retroattivo. http://blog.stackoverflow.com/2010/03/the-great-reputation-recalc-begins/ –

risposta

2

Ho fatto qualcosa di simile nella direzione opposta, usando un dizionario di System.Type oggetti per nomi di tipo SQL.

+0

Questo è un po 'quello che ho ma sto usando le stringhe piuttosto che i tipi effettivi. – Simon

4

Non è possibile eseguire "automaticamente" la conversione del tipo. In effetti, la maggior parte delle librerie ORM si basa sul tipo di proprietà effettivo utilizzato nella classe di entità di destinazione per eseguire la mappatura.

Vorrei utilizzare lo SQL-CLR Type Mapping dalla documentazione Linq a SQL come punto di partenza per creare codice di mappatura manuale. In molti casi ci sarà più di una mappatura valida.

2

Oppure si potrebbe un tavolo per la vostra traduzione automatica e di utilizzare tali valori (questo è un preliminare, non in gran parte testato ...):

e USED IT DIRECTLY FOR CLASS GENERATION o anche se vi piace generate the classes for the whole db

 /****** Object: Table [dbo].[DbVsCSharpTypes] Script Date: 03/20/2010 03:07:56 ******/ 
     IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DbVsCSharpTypes]') 
     AND type in (N'U')) 
     DROP TABLE [dbo].[DbVsCSharpTypes] 
     GO 

     /****** Object: Table [dbo].[DbVsCSharpTypes] Script Date: 03/20/2010 03:07:56 ******/ 
     SET ANSI_NULLS ON 
     GO 

     SET QUOTED_IDENTIFIER ON 
     GO 

     CREATE TABLE [dbo].[DbVsCSharpTypes](
      [DbVsCSharpTypesId] [int] IDENTITY(1,1) NOT NULL, 
      [Sql2008DataType] [varchar](200) NULL, 
      [CSharpDataType] [varchar](200) NULL, 
      [CLRDataType] [varchar](200) NULL, 
      [CLRDataTypeSqlServer] [varchar](2000) NULL, 

     CONSTRAINT [PK_DbVsCSharpTypes] PRIMARY KEY CLUSTERED 
     (
      [DbVsCSharpTypesId] ASC 
     )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
     ) ON [PRIMARY] 

     GO 


     SET NOCOUNT ON; 
     SET XACT_ABORT ON; 
     GO 

     SET IDENTITY_INSERT [dbo].[DbVsCSharpTypes] ON; 
     BEGIN TRANSACTION; 
     INSERT INTO [dbo].[DbVsCSharpTypes]([DbVsCSharpTypesId], [Sql2008DataType], [CSharpDataType], [CLRDataType], [CLRDataTypeSqlServer]) 
     SELECT 1, N'bigint', N'short', N'Int64, Nullable<Int64>', N'SqlInt64' UNION ALL 
     SELECT 2, N'binary', N'byte[]', N'Byte[]', N'SqlBytes, SqlBinary' UNION ALL 
     SELECT 3, N'bit', N'bool', N'Boolean, Nullable<Boolean>', N'SqlBoolean' UNION ALL 
     SELECT 4, N'char', N'char', NULL, NULL UNION ALL 
     SELECT 5, N'cursor', NULL, NULL, NULL UNION ALL 
     SELECT 6, N'date', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL 
     SELECT 7, N'datetime', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL 
     SELECT 8, N'datetime2', N'DateTime', N'DateTime, Nullable<DateTime>', N'SqlDateTime' UNION ALL 
     SELECT 9, N'DATETIMEOFFSET', N'DateTimeOffset', N'DateTimeOffset', N'DateTimeOffset, Nullable<DateTimeOffset>' UNION ALL 
     SELECT 10, N'decimal', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlDecimal' UNION ALL 
     SELECT 11, N'float', N'double', N'Double, Nullable<Double>', N'SqlDouble' UNION ALL 
     SELECT 12, N'geography', NULL, NULL, N'SqlGeography is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL 
     SELECT 13, N'geometry', NULL, NULL, N'SqlGeometry is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL 
     SELECT 14, N'hierarchyid', NULL, NULL, N'SqlHierarchyId is defined in Microsoft.SqlServer.Types.dll, which is installed with SQL Server and can be downloaded from the SQL Server 2008 feature pack.' UNION ALL 
     SELECT 15, N'image', NULL, NULL, NULL UNION ALL 
     SELECT 16, N'int', N'int', N'Int32, Nullable<Int32>', N'SqlInt32' UNION ALL 
     SELECT 17, N'money', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlMoney' UNION ALL 
     SELECT 18, N'nchar', N'string', N'String, Char[]', N'SqlChars, SqlString' UNION ALL 
     SELECT 19, N'ntext', NULL, NULL, NULL UNION ALL 
     SELECT 20, N'numeric', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlDecimal' UNION ALL 
     SELECT 21, N'nvarchar', N'string', N'String, Char[]', N'SqlChars, SqlStrinG SQLChars is a better match for data transfer and access, and SQLString is a better match for performing String operations.' UNION ALL 
     SELECT 22, N'nvarchar(1), nchar(1)', N'string', N'Char, String, Char[], Nullable<char>', N'SqlChars, SqlString' UNION ALL 
     SELECT 23, N'real', N'single', N'Single, Nullable<Single>', N'SqlSingle' UNION ALL 
     SELECT 24, N'rowversion', N'byte[]', N'Byte[]', NULL UNION ALL 
     SELECT 25, N'smallint', N'smallint', N'Int16, Nullable<Int16>', N'SqlInt16' UNION ALL 
     SELECT 26, N'smallmoney', N'decimal', N'Decimal, Nullable<Decimal>', N'SqlMoney' UNION ALL 
     SELECT 27, N'sql_variant', N'object', N'Object', NULL UNION ALL 
     SELECT 28, N'table', NULL, NULL, NULL UNION ALL 
     SELECT 29, N'text', N'string', NULL, NULL UNION ALL 
     SELECT 30, N'time', N'TimeSpan', N'TimeSpan, Nullable<TimeSpan>', N'TimeSpan' UNION ALL 
     SELECT 31, N'timestamp', NULL, NULL, NULL UNION ALL 
     SELECT 32, N'tinyint', N'byte', N'Byte, Nullable<Byte>', N'SqlByte' UNION ALL 
     SELECT 33, N'uniqueidentifier', N'Guid', N'Guid, Nullable<Guid>', N'SqlGuidUser-defined type(UDT)The same class that is bound to the user-defined type in the same assembly or a dependent assembly.' UNION ALL 
     SELECT 34, N'varbinary ', N'byte[]', N'Byte[]', N'SqlBytes, SqlBinary' UNION ALL 
     SELECT 35, N'varbinary(1), binary(1)', N'byte', N'byte, Byte[], Nullable<byte>', N'SqlBytes, SqlBinary' UNION ALL 
     SELECT 36, N'varchar', NULL, NULL, NULL UNION ALL 
     SELECT 37, N'xml', NULL, NULL, N'SqlXml' 
     COMMIT; 
     RAISERROR (N'[dbo].[DbVsCSharpTypes]: Insert Batch: 1.....Done!', 10, 1) WITH NOWAIT; 
     GO 

     SET IDENTITY_INSERT [dbo].[DbVsCSharpTypes] OFF; 
+2

Mi vergogno ogni volta che vedo i nomi dei tipi CLR in un database. È un perfetto esempio di http://thedailywtf.com/Articles/Soft_Coding.aspx. – Aaronaught

+0

dipende dall'utilizzo. Questo è usato per molti scopi, uno dei quali è la generazione del codice ... –

+0

+ se si dispone di sistema multiprovider ... ad es. utilizzando un db per configurare diversi RDBMS .... –

1

Conosco EF, nHibernate, Subsonic ecc. Potrebbe fare tutto questo per me, ma in questo caso, per vari motivi, devo fare il mio. :)

Perché non utilizzare SubSonic o uno degli altri strumenti di mappatura ORM per definire le conversioni di lavoro tra tipi di dati SQL e tipi di dati .Net - e poi rotolare la vostra soluzione di utilizzare queste informazioni sulle conversioni come base ?

Suppongo che non sia possibile utilizzare software di terze parti nella soluzione, ma è possibile arrivare a una soluzione.

6

Il motivo per cui la codifica hard è una cosa brutta è solo perché quando si inseriscono elementi in codice che cambiano, è fastidioso (e costoso) - non c'è altra ragione. Le cose che non cambiano, come il pi, o l'elenco dei giorni feriali, possono essere codificate a piacere e, di conseguenza, non si avranno costi di sviluppo aggiuntivi.

Quindi, questo problema non riguarda tanto il mantenimento di una tabella di mappatura manuale - nel codice, se necessario - poiché riguarda solo il mantenimento della tabella di mappatura in un unico punto.

Abbiamo eseguito il rollover della nostra classe di accesso ai dati, diversi anni fa. E certo, convertiamo manualmente (in un VB.Istruzione NET Select Case) da tipi .NET a tipi SQL. Penso che sia cambiato una volta, quando abbiamo dovuto aggiungere i tipi Enum.

Questo è una volta, in circa quattro anni. Facciamo un rilascio a settimana, in media - indovina quanto siamo preoccupati per il "sovraccarico" di codifica rigida di .NET -> mapping di tipo SQL?

Fatelo in un posto. Assicurati che tutto lo usi. E poi dimenticarlo. Ci sono altri problemi molto più difficili da risolvere.

+1

Sono d'accordo, non ero particolarmente interessato all'aspetto hard-coding, mi chiedevo solo se mi mancasse qualcosa con il mio approccio Select Select. :) – Simon