Como posso garantir que o Linq to Sql não substitui ou viola os valores padrão DB não anuláveis?

Eu tenho um banco de dados do SQL Server com uma tabela com esses campos:

  1. Um bit com o valor padrão 1, NOT NULL .
  2. Um smalldatetime com o valor padrão gettime() , NOT NULL .
  3. Um int sem valor padrão, IDENTITY , NOT NULL .

Quando eu gero o Linq to SQL para esta tabela, acontece o seguinte:

  1. O bit não recebe tratamento especial.
  2. O smalldatetime não recebe tratamento especial.
  3. O int está marcado como IsDbGenerated .

Isso significa que, quando eu fizer inserções usando o Linq to SQL, ocorrerá o seguinte:

  1. The bit will be sent as 0, overriding the default value. Right?
  2. The smalldatetime will be sent as an uninitialized System.DateTime, producing an error in SQL server since it doesn't fall with the SQL Server smalldatetime range. Right?
  3. The IsDbGenerated int will not be sent; the DB will generate a value which Linq to SQL will then read back.

What changes do I have to make to make this scenario work?

Para resumir: Eu quero campos não anuláveis ​​com valores padrão designados pelo banco de dados, mas não os quero IsDbGenerated se isso significa que não posso fornecer valores para eles ao fazer atualizações ou inserções usando o Linq to SQL. Eu também não os quero IsDbGenerated se isso significa que eu tenho que modificar manualmente o código gerado pelo Linq para SQL.

EDIT: A resposta parece ser esta é uma limitação no atual Linq para SQL.

14
Duplicar: stackoverflow.com/q/1120858/11683 (não votar para fechar, ambos são igualmente úteis).
adicionado o autor GSerg, fonte

4 Respostas

As classes geradas por Linq-To-Sql não selecionam os Constraints de Valor Padrão.

Talvez no futuro, mas o problema é que as restrições nem sempre são valores simples, elas também podem ser funções escalares como GetDate() , então o linq teria que saber como traduzi-las. Em resumo, nem sequer tenta. É também um tipo específico de banco de dados.

  • Você pode escrever um gerador de código para criar classes parciais de entidade, nas quais é possível extrair a configuração de valor padrão.
  • Como alternativa, o código da sua camada de negócios pode definir os padrões em construtores a partir de um arquivo xml, e tudo o que você precisa fazer é manter o arquivo xml atualizado.
  • Em vez de fazer o trabalho em construtores, você poderia emular sql e incluir valores padrão inspecionando o ChangeSet antes de enviar as alterações ao banco de dados.

The issue you are having is described at length in CodeProject - Setting Default Values for LINQ Bound Data

5
adicionado
"linq de alguma forma teria que saber como traduzir isso" - por que? Poderia permitir apenas passar nada em criar/atualizar e lê-los de volta depois. É assim que os campos IsDbGenerated funcionam, exceto pelo seu status somente leitura no lado do Linq.
adicionado o autor bzlm, fonte
Claro, isso poderia permitir, mas isso não acontece. O IsDbGenerated é apenas para colunas-chave neste momento. O "linq seria de alguma forma ..." é apenas a minha opinião sobre o porquê disso ser o caso.
adicionado o autor Robert Paulson, fonte
Parece que IsDbGenerated está agora disponível para colunas não chave também.
adicionado o autor Make it useful Keep it simple, fonte

Eu me deparei com o mesmo problema, bzlm, e chego à mesma conclusão. Simplesmente não há uma boa maneira de obter campos não-anuláveis ​​com valores padrão atribuídos pelo DB trabalhando com o Linq To Sql.

O trabalho em torno de que eu tenho ido é adicionar um método SetDefaults() muito semelhante ao que Robert Paulson vinculado no CodeProject e chamá-lo no construtor padrão da minha classe base de entidade de tabela. Ele funciona bem para mim, porque 95% do tempo, estou definindo um 0, string vazia ou getdate ().

3
adicionado
Sim, o mesmo aqui. Obrigado!
adicionado o autor bzlm, fonte

This means that when I make inserts using Linq to SQL, the following will happen:

  1. The bit will be sent as 0, overriding the default value. Right? - Correct
  2. The smalldatetime will be sent as an uninitialized System.DateTime, producing an error in SQL server since it doesn't fall with the SQL Server smalldatetime range. Right? - What is sent is DateTime.MinValue
  3. The IsDbGenerated int will not be sent; the DB will generate a value which Linq to SQL will then read back. - If DB generated is set then the value is created by the database, if not then Linq expects the user to set the value.

Sua melhor aposta é configurá-los no construtor do objeto, ou nos campos privados, se você não estiver usando propriedades automáticas.

2
adicionado
É possível, mas você não pode mudá-las depois do fato. Se você quiser alterá-los, crie-os no construtor.
adicionado o autor David Basarab, fonte
Não use o construtor, existe um método parcial especial chamado OnCreate para isso. Veja esta pergunta: stackoverflow.com/questions/82409/…
adicionado o autor Sam, fonte
Parece que você está dizendo que valores padrão em campos nos valores do SQL Server NÃO são possíveis de combinar com o Linq To SQL. Isso está correto?
adicionado o autor bzlm, fonte
Desculpe, não entendi. Oque é possivel? E o que não pode ser mudado depois do fato? É possível fazer o Linq To SQL executar uma inserção e ter os "valores padrão" especificados no banco de dados usado?
adicionado o autor bzlm, fonte
Na verdade, é OnCreated. As respostas de Longhorn213 são muito confusas, e ele também editou minha pergunta original por aparentemente nenhuma razão. Apenas ignore ele/ela.
adicionado o autor bzlm, fonte

Você pode criar outro arquivo para seu datacontext (classe parcial) e, em seguida, usar os métodos parciais InsertYOURENTITY e UpdateYOURENTITY para inspecionar suas propriedades e atribuir os valores apropriados. Chame ExecuteDynamicInsert ou ExecuteDynamicUpdate depois do seu código e você está pronto.

0
adicionado
Na verdade, a maneira recomendada de fazer isso no BLL é implementar o método parcial OnCreated() para a entidade, não o método sugerido. Ainda assim, não é relevante para a minha pergunta. Minha pergunta é sobre valores padrão no SQL Server, não na BLL.
adicionado o autor bzlm, fonte