47

sto lavorando con il Codice Prima caratteristica di Entity Framework e sto cercando di capire come posso specificare i tipi di dati di colonna che dovrebbe essere creato quando il database viene generato automaticamente.Come faccio a specificare che una proprietà dovrebbe generare una colonna di testo piuttosto che un nvarchar (4000)

Ho un modello semplice:

public class Article 
{ 
    public int ArticleID { get; set; } 

    public string Title { get; set; } 
    public string Author { get; set; } 
    public string Summary { get; set; } 
    public string SummaryHtml { get; set; } 
    public string Body { get; set; } 
    public string BodyHtml { get; set; } 
    public string Slug { get; set; } 

    public DateTime Published { get; set; } 
    public DateTime Updated { get; set; } 

    public virtual ICollection<Comment> Comments { get; set; } 
} 

Quando eseguo la mia applicazione, un database SQL CE 4.0 viene creato automaticamente con il seguente schema:

DB Schema

Fin qui, tutto bene ! Tuttavia, i dati sarò inserimento nelle proprietà Body e BodyHtml è normalmente maggiore della lunghezza massima consentita per il tipo NVarChar colonna, quindi voglio EF per generare Text colonne per queste proprietà.

Tuttavia, non riesco a trovare un modo per farlo! Dopo un po 'di usare Google e la lettura, ho provato a specificare il tipo di colonna utilizzando DataAnnotations, dalle informazioni che si trovano in this answer:

using System.ComponentModel.DataAnnotations; 

... 

[Column(TypeName = "Text")] 
public string Body { get; set; } 

Questo getta la seguente eccezione (quando il database viene eliminato e l'applicazione è re-run):

Schema specified is not valid. Errors: (12,6) : error 0040: The Type text is not qualified with a namespace or alias. Only PrimitiveTypes can be used without qualification. 

Ma non ho idea di che cosa spazio dei nomi o alias dovrei specificando, e non ho trovato nulla che mi avrebbe detto.

Ho anche provato a cambiare l'annotazione di cui al this reference:

using System.Data.Linq.Mapping; 

... 

[Column(DbType = "Text")] 
public string Body { get; set; } 

In questo caso un database è creato, ma la colonna Body è ancora un NVarChar(4000), così sembra che l'annotazione viene ignorata.

Qualcuno può aiutare? Questo sembra che dovrebbe essere un requisito abbastanza comune, ma la mia ricerca è stata infruttuosa!

+3

Il testo CE supporta? Guardando nella lista dei tipi di dati, posso vedere ntext, ma non il testo. –

+0

@ Damiano, hai ragione, grazie - aggiungi questo come risposta (e aggiungi un collegamento all'elenco dei tipi di dati) e accetterò. –

+0

Non sono riuscito a trovare un elenco online di tipi di dati: ho dovuto scaricare CE BOL per verificare. Sembra che Kristof Claes abbia aggiunto una risposta che copre lo stesso terreno. –

risposta

66

Apprezzo lo sforzo che è andato in risposta esistente, ma non ho trovato in realtà di rispondere alla domanda ... così ho provato questo, e ho scoperto che

[Column(TypeName = "ntext")] 
public string Body { get; set; } 

(quello da System.ComponentModel.DataAnnotations) funzionerà per creare una colonna di tipo ntext.

(Il mio problema con la risposta accettata è che sembra indicare che si dovrebbe cambiare il tipo di colonna nell'interfaccia, ma la domanda è come farlo a livello di codice.)

+3

La convalida del modello causa ancora problemi e genera un errore quando si tenta di inserire più di 4.000 caratteri, anche il database è impostato su ntext, ma sembra che quando legge "string", automaticamente indovina lunghezza massima = 4000, ignora il tipo nel database . Per me ancora non risolto. – Nestor

1

Hai provato minuscolo "text"? Per il this MSDN discussion, il fornitore di dati rileva la distinzione tra maiuscole e minuscole.

+0

L'ho provato, e non fa alcuna differenza: la colonna generata è ancora un 'varchar'. +1 per il link di discussione utile però, sembra che ci siano altri metodi che potrei provare-Avrò una lettura. –

9

Hai provato ntext? Ho appena creato un database SQL CE 4.0, e quando aggiungo manualmente una colonna a una tabella, ho notato che text non è disponibile nell'elenco dei tipi di dati, mentre ntext è. Proprio come si può scegliere nvarchar ma non varchar.

Sfortunatamente, la più grande dimensione di nvarchar che è possibile scegliere è 4000. Quindi nvarchar(max) non è un'opzione.

There is ntext but no text

+0

Ma come si definisce il modello, quindi la convalida del modello è un ntext e non una stringa (con max = 4000 predefinito). Ho impostato ntext sul mio db e ottengo ancora errori quando si aggiungono più di 4.000 caratteri. La proprietà del mio modello è di tipo stringa. – Nestor

+0

Hai provato a mettere '[Column (TypeName =" ntext ")]' sulla proprietà string? –

+0

Sì, ma non è stato sufficiente, ho aggiunto [MaxLength] per forzare la dimensione del campo di controllo nel database invece della lunghezza massima del tipo di stringa predefinita, e ora è ok. – Nestor

1

Questa DataAnnotation renderà Codice-First generare un nvarchar colonna (MAX) in SQL

[StringLength(1073741822)] 

Non sono sicuro se gli altri numeri grandi a fare lo stesso ... ho ottenuto questo uno usando la calcolatrice e il nvarchar (MAX) spec.

ho provato con SQL Server 2005 Express o no, ma non con CE

lo sto usando e funziona, ma mi piacerebbe sapere se è una buona idea o se sono manca qualcosa ... c'è un altro modo per fare in modo che il codice sappia che voglio nvarchar (MAX)?

1

Questa DataAnnotation renderà Codice-First generare un nvarchar colonna (MAX) in SQL anche :)

[StringLength(4010)] 
5

Il problema con l'utilizzo dell'attributo lunghezza della stringa esempio

[StringLength(4010)] 

è che ogni string> il numero di caratteri definiti nel l'attributo innescherà un'eccezione di convalida, che tipo di va contro ogni ragione per la quale si usa un formato non definito campo su una colonna, o si utilizza un numero enorme nell'attributo e perde qualsiasi convalida offerta dall'attributo. In definitiva si sta utilizzando un meccanismo di convalida per risolvere un problema di mappatura se si utilizza l'attributo StringLength, dove la risposta di Marcel Popescu utilizzando l'attributo Column è una soluzione molto migliore in quanto utilizza gli attributi di mapping per definire il tipo e consente comunque di utilizzare l'attributo StringLength per la convalida.

Un'altra opzione è utilizzare l'API fluente EF4 CTP5 e definire la mappatura della colonna nell'evento OnModelCreating in DbContext, ad es.

protected override void OnModelCreating(ModelBuilder modelBuilder){ 
    modelBuilder.Entity<Article>() 
    .Property(p => p.Body) 
    .HasColumnType("nvarchar(max)"); 
} 

Inoltre va notato che NText è un tipo di dati deprecato (ntext, text, and image (Transact-SQL) MS Books Online) e la raccomandazione è di usare NVARCHAR (MAX) al suo posto

+1

Per MS SQL CE non è deprecato, qui la domanda menziona il caso di MS SQL CE (4). – Nestor

+2

Vero, ho appena controllato Sql CE 4.0 Docs (http://msdn.microsoft.com/en-us/library/ms172424%28v=SQL.110%29.aspx) tuttavia il tipo ntext non può essere utilizzato con qualsiasi (sql server) e memorizza i dati in una pagina dati separata per il resto della tabella, in modo personale a meno che non avessi un motivo molto chiaro per non utilizzare l'uso di nvarchar (max) per le prestazioni e i motivi di funzionalità – nakchak

28

È possibile utilizzare il seguente DataAnnotation e Code-First sarà genera il tipo di dati di dimensioni massime consentito dal database. Nel caso di Sql CE risulta in una colonna di ntext sottostante.

[MaxLength] 

o utilizzando l'API fluente EF 4.1 RC ...

protected override void OnModelCreating(ModelBuilder modelBuilder){ 
    modelBuilder.Entity<Article>() 
     .Property(p => p.Body) 
     .IsMaxLength(); 
} 
+0

Per chiunque ancora alle prese con questo sotto SQL Server CE + codice EF prima, questa è la soluzione che stai cercando se hai provato typeName = ntext e hai ancora l'errore "il campo deve essere una stringa o un tipo di array con una lunghezza massima di" 4000 "" con lunghezza dati> 4000 ... [MaxLength] è tutto ciò che serve sulla colonna per renderlo ntext e consentire l'utilizzo dell'intera lunghezza dei dati – Rich

1

Ricordiamo che TypeName = "ntext" sembra funzionare, anche se devo anche aggiungere:

[StringLength(Int32.MaxValue)] 

per fermare il default una lunghezza di stringa di 128 che si intromette.

+1

Questo non funzionerà con SQL CE. Vedi la risposta di Michael qui usando invece [MaxLength]. – LordHits

4

lo so, questo è probabilmente un anno troppo tardi, ma:

Usa:

[StringLength(-1)] 

Questo creerà un campo ntext.Sono riuscito a memorizzare almeno 25Kbyte in quel campo usando il database della Compact Edition 4.0.

0

Nel caso in cui si fa add-migrazione e update-database utilizzando Package Manager, si può modificare il creare tabella aggiungendo StoreType come segue:

 CreateTable(
      "dbo.Table_Name", 
      c => new 
       { 
        ID = c.Int(nullable: false, identity: true), 
        Title = c.String(nullable: false, maxLength: 500), 
        Body = c.String(unicode: false, storeType: "ntext"), 
       }) 
      .PrimaryKey(t => t.ID); 
1

Se non si desidera annotare tutte le proprietà e si utilizza un EF contemporaneo, utilizzare una convenzione:

public class StringNTextConvention : Convention { 
    public StringNTextConvention() { 
    Properties<string>().Configure(p => p.HasColumnType("ntext"));      
    } 
} 

si può chiamare dal proprio onModelCreating():

modelBuilder.Conventions.Add(new StringNTextConvention()); 

e tutti i tuoi string s diventerà automagicamente nelle colonne ntext.

Problemi correlati