Verwenden von Effort (EF Testing Tool) mit berechneter Spalte




 Ich habe eine Reihe von Integrationstests, die direkt auf die Datenbank zugreifen - Testvoraussetzungsobjekte erstellen - die Tests durchführen und anschließend aufräumen - aber ich wollte den gleichen Ansatz im Speicher ausprobieren. 

 Ich habe gerade *[Mühe](http://effort.codeplex.com/)* in meinem Projekt verwendet und es funktioniert sehr einfach. Ich habe jedoch ein Problem, das ich versucht habe - aber nicht lösen können. 

 Eine der Tabellen, die ich mit Dummy-Daten füllen muss - als Testvoraussetzung - enthält eine berechnete Spalte (nvarchar, nicht null). Für den Umfang des Tests interessiert mich der Wert dieser Spalte nicht wirklich - aber selbst wenn ich Dummy-Daten einfüge, werden meine Daten ignoriert und dann wird ein Fehler ausgegeben: 


```
"Column 'x' cannot be null. Error code: GenericError"

```
  In meinen Tests verwende ich die gleiche edmx-Datei, wie sie vom eigentlichen Code verwendet wird. Das hindert mich daran, die edmx-Kopie ständig zu aktualisieren. 

 Gibt es einen Weg, auf dem ich den Test erzwingen kann, das edmx (zur Laufzeit) zu aktualisieren, so dass die Spalte eine nullbare nicht berechnete Spalte ist? [overriding OnModelCreating] oder gibt es eine Möglichkeit, einen Standardwert einzufügen (alles für diese Spalte), um diesen Fehler zu stoppen? [überschreibt SaveChanges] 

 Ich habe derzeit folgendes versucht: 

* Anfügen der Objekte mit .Attach () anstelle von .Add ()
* Setzen Sie den EntityState nach dem Hinzufügen auf Unverändert
* Erzwingt den Wert durch Entry.OriginalValues ​​[diese Werte, da sich die Entität im hinzugefügten Zustand befindet]

 **Bearbeiten:** 

 Ich habe versucht, die *OnModelCreating-* Methode zu überschreiben, aber ohne Erfolg, da dies DB-First ist. 


```
modelBuilder.Entity<Entity_Name>().Property(p => p.x).IsOptional().HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

```
Der Grund für das Problem war ein Fehler in der Effort-Datenbank. Wenn die berechnete Spalte auf nicht nullwertfähigen Spalten basiert, kann die berechnete Spalte auch automatisch nicht nullwertfähig werden. Daher erwartete die Effort-Datenbank einen Wert ungleich Null. Mit dem neuesten Update ist das Problem behoben. Sie müssen das globale `EntityFrameworkEffortManager.UseDefaultForNotNullable` Flag auf true setzen. 

 Siehe die [Ausgabe auf Github](https://github.com/zzzprojects/EntityFramework-Effort/issues/62#issuecomment-471199839)
Wenn eine Spalte in der Datenbank nullfähig ist, hat die Ergebnisklasse auch eine nullfähige Eigenschaft. 

 Wenn beispielsweise eine `Order` eine `Datetime` Spalte mit dem Namen `CreatedDate` , sieht die resultierende `Order` Klasse in etwa wie folgt aus: 


```
public partial class Order: EntityObject
{
  ...
  private DateTime? _createdDate;
  ...
}

```
  Wenn \_ `createdDate` keinen Wert hat, wenn Sie `ObjectContext.SaveChanges()` aufrufen, wird eine `System.DBNull` automatisch als Teil des Befehls insert oder update an die Datenbank gesendet. 

 Hoffe das hilft Alex <p>so erhalten sie die liste der spalten in der standardreihenfolge ohne die fehlerhafte spalte:</p><pre><code>select string\_agg(quote\_ident(attname), ', ' order by attnum) from pg\_attribute where attrelid = 'myschema.mytable'::regclass and not attisdropped -- no dropped (dead) columns and attnum &gt; 0 -- no system columns and attname &lt;&gt; 'bad\_column' -- case sensitive! </code></pre><p>oder einfach <code>where attrelid = 'mytable'::regclass</code>, wenn sie darauf vertrauen, dass der suchpfad <a href="https://stackoverflow.com/questions/9067335/how-does-the-search-path-influence-identifier-resolution-and-the-current-schema/9067777#9067777"></a> in das richtige schema aufgelöst wird.</p><p> <a href="http://www.postgresql.org/docs/current/interactive/functions-string.html#functions-string-other"><code>quote\_ident()</code></a> fügt bei bedarf doppelte anführungszeichen hinzu.</p><p>ich habe die gleiche frage <a href="http://www.postgresql.org/message-id/flat/1180483885.536572.84550@q69g2000hsb.googlegroups.com#1180483885.536572.84550@q69g2000hsb.googlegroups.com">2007 auf pgsql-general</a> gestellt. es war damals postgres 8.2. süße erinnerungen ...</p><p>verbunden:</p><ul> <li> <a href="https://stackoverflow.com/a/24089729/939860">so überprüfen sie, ob eine tabelle in einem bestimmten schema vorhanden ist</a> </li> </ul> <p>ich denke, dies wirft weitere fragen und potenzielle probleme auf:</p><ol> <li>ist es wirklich notwendig, zwei getrennte arten von feldern für diese arten von zahlen zu haben? die tatsache, dass sie probleme haben, sie richtig zu kennzeichnen, bedeutet, dass dies wahrscheinlich zu einer schlechten benutzererfahrung führt.</li> <li>was ist, wenn der benutzer der meinung ist, dass die antwort eine dezimalstelle enthält, aber nur eine ganze zahl eingeben darf? sollten sie auf- oder abrunden?</li> <li>gibt es eine möglichkeit, sie nur mit einem nummernfeld zu versehen und den rest programmgesteuert zu erledigen? vielleicht dezimalstellen runden oder entfernen?</li> </ol><p>wenn sie sie nicht zu einem feldtyp kombinieren können, können sie sie auf jedem etikett explizit angeben:</p><ul> <li>geben sie eine zahl ein (dezimalstellen erlaubt)</li> <li>geben sie eine zahl ein (keine dezimalstellen)</li> </ul> <p>row\_number () ist eine ranking-fensterfunktion, und ranking-fensterfunktionen erfordern eine obligatorische order by-klausel. wenn sie versuchen, es ohne order by zu schreiben, wird ein syntaxfehler angezeigt.</p><pre><code>select row\_number() over() from (values ('a'), ('b'), ('c')) as x(y); -- msg 4112, level 15, state 1, line 1 -- the function 'row\_number' must have an over clause with order by. </code></pre><p>der trick mit der unterabfrage wurde von jemandem entdeckt, der darüber als leistungsoptimierung gebloggt hat. sql server führt immer eine sortieroperation aus, da konstanten für die order by-klausel nicht zulässig sind:</p><pre><code>select row\_number() over(order by null) from (values ('a'), ('b'), ('c')) as x(y); -- msg 5309, level 16, state 1, line 1 -- windowed functions, aggregates and next value for functions -- do not support constants as order by clause expressions. </code></pre><p>und ganzzahlen, die als indizes behandelt werden, sind es auch nicht:</p><pre><code>select row\_number() over(order by 1) from (values ('a'), ('b'), ('c')) as x(y); -- msg 5308, level 16, state 1, line 1 -- windowed functions, aggregates and next value for functions -- do not support integer indices as order by clause expressions. </code></pre><p>es stellt sich heraus, dass sie diese einschränkung aufgrund eines fehlers im code umgehen können, indem sie eine unterabfrage verwenden, die aus irgendeinem grund zulässig ist, und den sortieroperator entfernen.</p><pre><code>select row\_number() over(order by (select 1)) from (values ('a'), ('b'), ('c')) as x(y); </code></pre><p> <a href="https://i.stack.imgur.com/i76qa.png">(<img src="https://i.stack.imgur.com/i76qa.png" alt="no sort operator"></a> </p><p>sie können eine beliebige konstante in der unterabfrage verwenden. null erinnert wahrscheinlich an die gewohnheit, select null in exists-prädikaten zu verwenden, die in der frühen geschichte von sql server einen leistungseinfluss im gegensatz zu * oder einem anderen spaltenausdruck hatten der optimierer war nicht klug genug, um ihn zu ignorieren.</p><p>hth</p><p><strong> [~ # ~] update [~ # ~] </strong> @ erik-darling kommentierte, dass sie es auch umgehen können, indem sie berechnete ausdrücke verwenden:</p><pre><code>you can do select row\_number() over (order by 1/0); </code></pre> Ich treffe dasselbe Problem in EF RC1. und ich habe eine Entdeckung, hoffe, dass es dir helfen kann. Ich erstelle ein Projekt, um das Entitätsmodell und EF DBContext einzubeziehen. dann Web-Projekt Referenz das Projekt. führe diese Befehle aus, funktioniert nicht: 

1. dnx ef migrations fügt MyFirstMigration hinzu
2. dnx ef Datenbank - Update [Ergebnisse](http://i.stack.imgur.com/Ftbey.png)

 Aber wenn ich die DBContext-Klasse in mein Web-Projekt verlagern, funktionieren die Modelle immer noch in einem anderen Projekt. [Neues Ergebnis](http://i.stack.imgur.com/JgMbG.png) 

 Stellen Sie in meinem Szenario sicher, dass DBContext im Webprojekt vorhanden ist. <p>angenommen, sie verwenden ms sql server (was sie nicht sind, finden sie im <strong> update unten </strong>):</p><blockquote> <p>eine tabelle kann nur eine zeitstempelspalte haben. der wert in der timestamp-spalte wird jedes mal aktualisiert, wenn eine zeile mit einer timestamp-spalte eingefügt oder aktualisiert wird. diese eigenschaft macht eine timestamp-spalte zu einem schlechten kandidaten für schlüssel, insbesondere für primärschlüssel. bei jeder aktualisierung der zeile wird der zeitstempelwert und damit der schlüsselwert geändert. wenn sich die spalte in einem primärschlüssel befindet, ist der alte schlüsselwert nicht mehr gültig und fremdschlüssel, die auf den alten wert verweisen, sind nicht mehr gültig. wenn in einem dynamischen cursor auf die tabelle verwiesen wird, ändern alle aktualisierungen die position der zeilen im cursor. befindet sich die spalte in einem indexschlüssel, generieren alle aktualisierungen der datenzeile auch aktualisierungen des index.</p> </blockquote><p>informationen zu <a href="http://msdn.microsoft.com/en-us/library/aa260631%28v=sql.80%29.aspx"> msdn </a> </p><p>wenn sie datums-/uhrzeitinformationen für eine zeile speichern müssen und diese datums-/uhrzeitänderung nicht haben, verwenden sie datetime. andernfalls verwenden sie timestamp.</p><p><strong> beachten sie auch: </strong> ms sql server-zeitstempelfelder sind weder datum noch uhrzeit. sie sind binäre darstellungen der relativen reihenfolge, in der die daten geändert wurden.</p><h2>aktualisieren</h2><p>wie sie aktualisiert haben, um mysql zu sagen:</p><blockquote> <p>timestamp-werte werden zum speichern von der aktuellen zeitzone in utc konvertiert und zum abrufen von utc zurück in die aktuelle zeitzone konvertiert. (dies tritt nur für den timestamp-datentyp auf, nicht für andere typen wie datetime.)</p> </blockquote><p>zitat aus <a href="http://dev.mysql.com/doc/refman/5.0/en/timestamp.html">mysql-referenz</a> </p><p>insbesondere:</p><blockquote> <p>wenn sie einen timestamp-wert speichern, dann die zeitzone ändern und den wert abrufen, unterscheidet sich der abgerufene wert von dem von ihnen gespeicherten wert.</p> </blockquote><p>wenn sie also eine anwendung in mehreren zeitzonen verwenden und das datum und die uhrzeit benötigen, um die einstellungen der einzelnen benutzer widerzuspiegeln, verwenden sie timestamp. wenn sie unabhängig von der zeitzone konsistenz benötigen, verwenden sie datetime</p> Sie können verwenden 


```
DbConfiguration.SetConfiguration(new YourDbConfiguration());

```
  Sie können also Ihre Konfiguration verwenden, ohne ein Attribut zu verwenden. 

 Aber wenn ich benutze 


```
public CeDbConfiguration()
{
 SetDefaultConnectionFactory(new SqlCeConnectionFactory(SqlCeProviderServices.ProviderInvariantName,
                                                        @"c:\test",
                                                        @"c:\test\db.sdf"));
SetProviderServices(SqlCeProviderServices.ProviderInvariantName,
                    SqlCeProviderServices.Instance);
}

```
  Um eine SQL CE Factory zu konfigurieren, wird der Pfad *'C: \ test'* ignoriert und ich muss auch Database.DefaultConnectionFactory setzen !! <p>bitte führen sie diese abfrage aus:</p><pre><code>select data\_bb / power(1024,1) data\_kb, data\_bb / power(1024,2) data\_mb, data\_bb / power(1024,3) data\_gb from (select sum(data\_length) data\_bb from information\_schema.tables where table\_schema not in ('information\_schema','performance\_schema','mysql')) a; </code></pre><p>dies gibt ihnen eine baseball-figur. die kolumne <code>index\_length</code> wird nicht verwendet, da mysqldump keine indizes, sondern nur daten ausgibt. um sicher zu gehen, sollten sie es immer sofort gzip:</p><pre><code>mysqldump --all-databases --routines --triggers | gzip &gt; mysqldata.sql.gz </code></pre><p>versuche es !!!</p> <p>es gibt optionen, die ihnen dabei helfen:</p><pre><code> --insert-ignore insert rows with insert ignore. --replace use replace into instead of insert into. -t, --no-create-info don't write table creation info. </code></pre><p>denken sie an dieses paradigma</p><ul> <li>mysqldump alles von db1 in dump1</li> <li>laden sie dump1 in db3</li> <li>mysqldump alles aus db2 mit --replace (oder --insert-ignore) und --no-create-info in dump2</li> <li>laden sie dump2 in db3</li> </ul> <p>es ist eine einschränkung des dbms - soweit ich weiß in allen. und das nicht nur beim hinzufügen einer spalte, sondern auch beim neuanordnen von spalten. wenn wir eine <code>unique</code> -einschränkung für <code>(a1, a2)</code> haben, können wir keine <code>foreign key</code> hinzufügen, die <code>references (a2, a1)</code>, es sei denn, es gibt eine eindeutige einschränkung für diese <code>(a2, a1)</code> das ist im wesentlichen redundant.</p><p>es wäre nicht besonders schwierig, dies als feature hinzuzufügen:</p><blockquote> <p>wenn es eine <code>unique</code> -einschränkung für <code>(a)</code> gibt, ist auch jede <code>(a, b, c, ..., z)</code> oder <code>(b,c, ...a, ...z)</code> kombination garantiert <code>unique</code>.</p> </blockquote><p>oder die verallgemeinerung:</p><blockquote> <p>wenn für <code>(a1, a2, ..., an)</code> eine <code>unique</code> -einschränkung besteht, ist auch jede <code>(a1, a2, ..., an, b1, b2, ..., bm)</code> - kombination oder neuanordnung <code>unique</code> garantiert.</p> </blockquote><p>es scheint, dass es nicht gefragt wurde oder nicht als hoch genug eingestuft wurde, um implementiert zu werden.</p><p>sie können jederzeit - im jeweiligen kanal - eine anfrage für die zu implementierende funktion stellen. oder implementieren sie es sogar selbst, wenn das dbms open source ist, wie postgres.</p>