[Databases] Често срещани проблеми


24

Привет, колеги :-)

Предполагам ще се съгласите че базите данни са най-проблематичното нещо с което сме се сблъсквали в академията. Поне аз досега съм си счупил главата поне по 20 различни начина, а съдейки по броя проблеми във форума, не съм единствен. Ето един кратък списък с някои от проблемите на които съм се натъквал, с цел евентуално да спестя на някого малко ядове. Благодарности на колегите, които ми помогнаха да ги събера. Всеки който желае може да допълва темата, всякакви съвети и предупреждения са добре дошли.

Леснини:

* за споделяне и тестване на SQL снипети - http://sqlfiddle.com

* за синтаксис на connection низове - http://connectionstrings.com/

* винаги когато имате изключение, проверявайте .InnerException - често там се крие много полезна информация за диагностицирането на проблема

Общи проблеми:

* бавно свързване през ADO.NET/Entity Framework

- в поне три случаи досега проблемът беше причинен от JustMock/JustTrace. При едни колеги проблемът се реши след като пуснаха и изключиха JustTrace. При други - след като un-инсталираха JustMock (можете да опитате само да изключите профайлъра му от Telerik -> JustMock -> Disable profiler)

- ако използвате TCP/IP, проверете дали firewall-а не ви прави проблеми

Синтаксис:

* не забравяйте особеностите в синтаксиса на SQL: например, сравняването е с едно =, низовете са с единични кавички ('), а двойните кавички са за имена на таблици. Запазените процедури обикновено се викат с пълен префикс (примерно dbo)

* IDENTITY в MySql е AUTO_INCREMENT, а в SQLite - AUTOINCREMENT

* ключовата дума INTO в "INSERT INTO ..." не е задължителна в SQL Server и MySQL, но задължителна в SQLite, вероятно и в Excel.

* литералните таблици нямат стандартен синтаксис: следното понякога работи в SQL Server, понякога не:

SELECT *, dbo.udf_FinalSum(initialSum, yearlyInterestRate, months)
FROM (
    VALUES (100, 0.10, 12),
           (100, 0.20, 12),
           (100, 0.20, 18),
           (100, 0.20, 24)
           ) AS Arguments(initialSum, yearlyInterestRate, months)
GO

* 64-битово число с плаваща запетая е REAL, не DOUBLE

Excel

* проблем с типа данни когато четете числа
в Excel числата са Double по подразбиране, затова използвайте GetDouble

* липса на драйвери когато се опитвате да се свържете към xslx - инсталирайте това , сложете Provider=Microsoft.ACE.OLEDB.12.0 и Extended Properties=Excel 12.0 в connection string-а (благодарности на kirov). Можете да проверите кои драйвери имате като потърсите името на някой драйвер в windows registry (клон HKEY_CLASSES_ROOT)

SQLite

* "An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)"

Причина: ползвате библиотеката "system.data.sqlite" и сте свалили dll от версия несъвместима с архитектурата на компютъра.
Решение: свалете правлилният dll и сменете build target на x86 или x64 от Project Properties

SQL Server

* проблем с включването през TCP/IP:

- от SQL Configuration Manager трябва да включите SQL Server Browser, да сложите "Enabled" на TCP/IP и да рестартирате сървъра (можете да проверите дали слуша на порт 1433 с "netstat /a" в конзолата). Ако се свързвате от друг компютър, трябва да проверите firewall-а на сървъра и евентуално да му пуснете network discovery за да се вижда в локалната мрежа (за последното не съм сигурен).

* проблем с четенето на image данни: трябва да изпуснете първите 78 байта, в тях SQL Server пази метаданни (отново благодарности на kirov):

const int OLE_METAFILEPICT_START_POSITION = 78;

using (var fs = File.OpenWrite(name + ".jpg"))
using (var stream = reader.GetStream(1))
{
    stream.Seek(OLE_METAFILEPICT_START_POSITION, SeekOrigin.Begin);
    stream.CopyTo(fs);
}


SQL Management Studio

* "error not found" когато attach-вате -
Ако mdf и ldf файловете съществуват, по всяка вероятност трябва да настроите permission-ите им - десен бутон на файла, security, edit, добавяте пълен достъп за everyone (примерно)

* когато скриптирате базата, не забравяйте да изберете "schema and data", както каза Наков. Опцията е заровена в диалога "Advanced" и е много лесно да я пропуснеш и да запазиш само схемата.


ADO.NET

* DataType mismatch - проверете дали не пъхате грешен тип данни, особено низове вместо числа, низове с по-голяма дължина от декларираната в таблицата, или грешен тип числа - в SQL често няма конверсии по подразбиране там където сме свикнали да ги очакваме.

Entity Framework

* .SaveChanges хвърля DbEntityValidationException: "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."

Когато сте обработвали данните, сте нарушили някой constraint. Можете да проверите точната причина като разгледате изключението в Debug -> Windows -> Immediate Window:

($exception as System.Data.Entity.Validation.DbEntityValidationException)
    .EntityValidationErrors
    .First()
    .ValidationErrors
    .First()


Ако вашата версия на VS не поддържа специалната променлива $exception, ще трябва да прихванете изключението в catch и да го разгледате оттам:

try
{
    ...
    entities.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
    // check exception validation errors
}


* DbUpdateException при .SaveChanges() - вероятно се опитвате да запазите дублиращ се обект в базата

* The specified type member '...' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. Source=System.Data.Entity

- проверете ламбдите които използвате - те всъщност не се изпълняват , а се компилират в "expression trees" от които Entity Framework генерира SQL. В резултат, се подържат само най-базовите неща - сравнения, аритметика, new изрази, string.StartsWith/.EndsWith/.Contains и т.н. В краен случай ще се наложи от даден момент да дръпнете данните локално и да ги дообработите в C#

var customers = entities.Customers
        .Where(c => c.CustomerId > 1000) // sql-friendly
        .ToList() // fetch in memory
        .Where(c => EUMembers.Contains(c.Country)); // we have to do this in C#


* липсващ шаблон ADO.NET Entity Framework Data Model във Visual Studio: проверете предложенията в тази тема

* ако ползвате Database-first и модела не иска да се update-не, можете да изтриете .edmx файла и да го генерирате отново (като гледате да не си затриете partial-класовете), или ако разликите са малки, да го отворите с текстов редактор и да нанесете промените ръчно (след това не забравяйте да пуснете T4 генерацията с десен бутон -> Run custom tool, както и да build-нете проекта)

* има още доста проблеми които са специфични за Database-first подхода, обикновено се появяват ако в самата база данни сте сбъркали нещо в схемата (пропуснали сте да сложите primary key, сложили сте foreign key да сочи грешната колона и т.н.). Също така трябва да имате предвид че имената които генерира Entity Framework понякога са подвеждащи.


в Databases от staafl (5770 точки)


Отговори



8

Браво, много полезна тема. Който иска, може да допълва темата.

Аз бих добавил към SQL Management Studio: Когато ви дава грешка "Saving changes is not permitted" да изключите опцията "Designer -> Prevent saving changes that require table re-creation."

Друг проблем в SQL Management Studio обикновено като атачвате база не ви дава права да добавяте диаграми, тогава давате десен бутон на базата -> Properties -> Files и сетвате Owner на вашия user или на sa (sys admin).


от Nikolay.IT (39117 точки)


1
При стартиране на приложение, които използва Entit Framework модел, ако ви хвърля exception, че базата се използва -> Затворете нещата свързани с базата в Management Studio или спрете Management Studio.

от SVGN_H (3048 точки)


2
Добавка към свързване към SQL Server - ако гореописаното не е достатъчно в същото меню включвате pipe-овете, ако пак нямате опция "start" на server browser-a:
в Start -> десен клик на Computer (win7) -> Manage намирате Services and Applications -> Services и вдясно SQL Server Browser -> десен клик, пускате, после си го пускате от SQL Config Manager-a

от spareva (1375 точки)


0
Благодаря!!!! Изключително полезна тема, която ми помогна да разреша 2 от проблемите, с които се борех от няколко дни!!!!

от repuhka (5 точки)


0
* Транзакции: при използването на TransactionScope, .SaveChanges() гърми с "underlying provider failed to open", а inner exception показва "MSDTC not available" - трябва да стартирате service-a “Distributed Transaction Coordinator”. Като цяло, винаги гледайте вътрешното изключение, често разковничето на проблема е именно там.

от staafl (5770 точки)


0

* Entity Framework: грешка "Unable to determine the principal end of the relationship" - вероятно създавате нови обекти с IDENTITY ключове и се опитвате да зададете връзки между тях директно, преди да сте запазили обектите в базата; това не е възможно, тъй като преди SaveChanges, стойностите на ключовете още не са генерирани. Вместо директно да използвате Id колоните, използвайте навигационните property-та.

Грешно:

var pesho = new Human { FirstName = "Pesho", LastName = "Peshev" };
var account = new Account { Balance = 1000, PersonId = pesho.Id };


Правилно:

var account = new Account { Balance = 1000, Person = pesho };

* Entity Framework - VS мистериозно се оплаква че context класът не е IDisposable - забравили сте да добавите reference към EntityFramework.dll в приложния проект - трябва да се реферира от всеки проект, не само модела.


от staafl (5770 точки)


1

При вързването към SQLite база, през Entity Framework, ползвайте провайдъра за 32bit Windows, независимо, че сте на 64 битов :)


от Teodor92 (13062 точки)


1
Ако се опитвате да правите SQL заявка през EntityFramework, чрез SqlCommand.ExecuteNonQuery(), се случва да хвърля ексепшън "Invalid syntaxis near GO".
Просто изтрийте навсякъде "GO" командите, по някаква причина EF не ги харесва.

от stann1 (1378 точки)