Въпрос: Кога е нужно да слагам в класовете си свойства, и кога мога да слагам публични полета? Не е ли вторият вариант по-удобен, особено когато едно поле не се валидира по никакъв начин? Отговор



Дата27.04.2017
Размер59.42 Kb.
Отговори на някои често срещани въпроси

I. Общи въпроси:



Въпрос: Кога е нужно да слагам в класовете си свойства, и кога мога да слагам публични полета? Не е ли вторият вариант по-удобен, особено когато едно поле не се валидира по никакъв начин?

Отговор: Винаги е по-добре да се ползват свойства, както и да се спазва конвенцията по именуването. Това води до много по-лесна поддръжка на кода. Ако аксесоарите методи не извършват допълнителни операции, то скоростта на изпълнение не намалява.

Въпрос: Имам конзолно приложение и не мога да изпиша нищо на български например:
"Натиснете някой клавиш за продължение ..." , дава ми само ????.

Отговор: Windows конзолата по принцип не подържа Unicode. За да ползваш кирилица, трябва от Regional Options в Control Panel да зададеш Bulgarian в Language for non-Unicode programs полето.

Въпрос: Трябва ли проекта да е на български език?

Отговор: Приема се и английски език.

Въпрос: Как най-лесно мога да създавам обекти и техните properties от даден клас по време на изпълнение без да зная какви са те по време на компилация - или искания клас и свойствата ги чета от файл или потребителят ги вкарва по време на изпълнение да кажем в TextBox?

Отговор: За тази цел се използва Reflection.

Въпрос: Как лесно мога да променям конфигурационния файл по време на изпълнение? Има ли клас, както е за четенето от него.


Отговор: В .NET Framework 1.1 не е предвидено лесното записване в конфигурационния файл. Можем да направим собствен клас, който променя app.config чрез XML парсера.
Ето пример как да се промени даден ключ:

XmlDocument doc = new XmlDocument();


string fileName = "App.config";
try
{
doc.Load(fileName);
foreach (XmlNode node in doc["configuration"]["appSettings"])
{
if(node.Name == "add")
{
if (node.Attributes.GetNamedItem("key").Value == key)
{
node.Attributes.GetNamedItem("value").Value = value;
break;
}
}
}
doc.Save(fileName);
doc = null;
}
catch (XmlException e)
{
Console.WriteLine(e.Message);
}

II. Въпроси за Windows Forms



Въпрос: Имам форма, която вика друга форма (нито една от тях не е MDI контейнер) обаче като опитам да затворя първата форма (тази която вика другата) не мога.

Отговор: Ако втората форма е модална, не може. С Show() ще може да се затвори приложението, с  ShowDialog() няма да може.

Въпрос: Имам си един ListBox и при всяка нова селекция в TreeView-то трябва да му refresh-вам данните. До тук добре. Ето кода:

cds = srv.GetCDFromCategory(path);


lstBoxCDs.DataSource = cds.Tables["CDs"];
lstBoxCDs.DisplayMember = "name";

Първите два пъти като цъкам из TreeView-то всичко е ОК. После спира да refresh ListBox-а. При дебъг всичко е наред, в DataSet-а си има таблица със съответните cd-та в нея.



Отговор: Това е добре известен проблем. Трябва да се махне binding-а и да се сложи наново.
От типа на:

lstBoxCDs.DataSource = null; // Remove binding


cds = srv.GetCDFromCategory(path);
lstBoxCDs.DataSource = cds.Tables["CDs"];
lstBoxCDs.DisplayMember = "name";

Въпрос: Трябва ми в Windows Form да запомням една int стойност като влизам от една в друга форма. Пробвах да направя public, но като вляза в друга форма и то винаги е 0.

Отговор: Най-правилно е да се предава стойността в конструктора на новосъздадената форма.

Въпрос: Искам да направя така че в ComboBox  да могат да се избират само items от неговия списък, т.е да не може да се пише друго. Има ли някое специално свойство за тази цел?

Отговор: Да: DropDownStyle = DropDownList

Въпрос: Windows Forms:
Имам две форми и искам да премина от едната в другата.

Отговор: Ако едната форма е родителска и от нея се вика другата, може да се скрие първата. Ако се унищожи, ще се унищожат и двете форми, но можеш да се скрие с Hide() и когато се приключи с дъщерната форма, да се затвори и родителската. Може да стане ето така:

childForm.Show();


Hide();

В Windows Forms има разлика между Form.Hide() и Form.Close().


Ако скриеш всички отворени форми на приложението, то няма да спре. За да спре приложението трябва всички негови форми да за затворени. Hide() просто скрива формата - тя си остава активна, получава си съобщенията и т.н., но е невидима.
Close() затваря формата и унищожава всички ресурси, свързани с нея (най-вече освобождава hWND хендъла) и спира обработката на съобщения.

III. Въпроси за бази данни



Въпрос: Как се escape-ва символът ' (апостроф) при SQL заявка?

Отговор: Пишат се два апострофа един след друг:
select 'aaa''a' -> aaa'a
Това не се налага, когато се ползват параметризирани заявки чрез ADO.NET Data Provider. Това е препоръчителният начин.


Въпрос: Съхранявам картинките в базата. При достъп до тях не могат да се визуализират коректно. Има ли ограничение на размера за тип image? Полето е 16 байта.

Отговор: При взимането на картинките от базата трябва да бъде възстановено оригиналното им разширение: .png, .jpg и т.н. Картинките се пазят извън таблицата, полето от 16 байта е указател към тях и не представлява ограничение.


Въпрос: Искам да си променя вече съществуваща картинка в SQL база данни. Как трябва да ми изглежда SQL командата с UPDATE. Възможно ли е да стане с INSERT и с параметър и дали INSERT-а няма да омаже вече съществуващите неща.

Отговор: Ето пример за такъв UPDATE:

sqlCommand.Connection=....


sqlCommand.CommandText = "update TableImage set TableImage_Image = @newImage where TableImage_ImageID = @oldImageID"

byte[] image = ... картинката е в този масив


sqlCommand.Parameters.Add( "@newImage", image );

int id = 10


sqlCommand.Parameters.Add( "@oldImageID", id )

sqlCommand.ExecuteNonQuery();

В примера:
1. TableImage е името на таблицата за която стажа дума
2. TableImage_Image е колоната с image-а
3. TableImage_ImageID е ID, по което да можеш да различаваш картинките.


Въпрос: Защо, когато имам активна транзакция в SqlConnection и не мога да правя заявки, които не участват в транзакцията? Това става само докато е активна транзакцията. Например, следният код не работи:

IDbTransaction tran;


tran.BeginTransaction();

IDbCommand cmd = aSqlConnection.CreateCommand();


cmd.Transaction = tran;
cmd.CommandText = ...
cmd.ExecuteNonQuery();

IDbCommand cmd1 = aSqlConnection.CreateCommand()


cmd1.CommandText = ...
cmd1.ExecuteNonQuery();

tran.Commit();



Отговор: За да се правят заявки извън транзакцията, трябва да отвори нова връзка.

Въпрос: Обхождам таблица с автори с IDataReader и за всеки автор обхождам публикациите му с друг IDataReader. Получавам следното изключение:
Unhandled Exception: System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed first.

Отговор: Това е добре известна слабост на SqlClient DataProvider - за всяка връзка с базата се позволява един отворен курсор. В случая проблема може да се реши като се отваря нова връзка при обхождане на публикациите.


Въпрос: Как да се съхраняват дати в базата данни?

Отговор: За работа с дати се прави така:

1) Всички колони, които съдържат дати, трябва да се от тип дата в базата данни (DateTime в SQL Server)

2) Всички методи, които приемат като параметър или връщат дати по някакъв начин трябва да приемат/връщат типът System.DateTime, а не стринг!!

3) Винаги, когато се прави преобразуване от дати към стринг или обратното, трябва да се задава култура или точен формат. Иначе приложението не е преносимо и в друга среда не може да работи правилно.



Въпрос: Как да си пренеса MSSQL базата данни от един компютър на друг? Например за защитата?

Отговор: Има 2 начина да стане това:

1 начин - backup/restore

За backup на MS SQL база данни се прави така:

SQL Server Enterprise Manager -> Databases -> твоята база -> All Tasks -> Backup Database -> задаваш някакво име на файл и натискаш бутона "OK"

За restore на MS SQL база данни се прави така:

SQL Server Enterprise Manager -> All Tasks -> Restore Database -> From device -> Select devices -> избираш файла -> избираш името на базата, под което ще възстановяваш и натискаш бутона "OK"


2 начин - копиране на файловете

Прави се така:

1) SQL Server Enterprise Manager -> All Tasks -> Detach Database

2) Копират се файловете на базата данни от директория:

C:\Program Files\Microsoft SQL Server\MSSQL\Data

За всяка база има по 2 файла - базата.mdf и базата.ldf

3) На новата машина след като се копират базата.mdf и базата.ldf в C:\Program Files\Microsoft SQL Server\MSSQL\Data се атачва базата:

SQL Server Enterprise Manager -> All Tasks -> Attach Database


Въпрос: Като добавям запис на кирилица в базата данни и след това като чета от него ми излизат ????.

Отговор: Полето в базата данни трябва да е от тип nvarchar за да се използва коректно кирилица. Ако е varchar се наблюдава описаният проблем.


Въпрос: Имам реализирана дървовидна структура, като в таблицата всеки запис има PK и съответно FK, който сочи към родителя му – в същата таблица. Как да подходя за да изтрия даден елемент и всичките му деца?

Отговор: Тук не може да се използва CASCADE DELETE, нито рекурсивна записана процедура с курсор, тъй като курсорът е глобален. Рекурсивното триене и като цяло операциите свързани с дървовидни структури в SQL Server са доста разискван проблем. Добри примери има в групите на Гугъла – като тази тема (виж http://groups-beta.google.com/group/microsoft.public.sqlserver.programming/browse_thread/thread/bab5ab169f26dc23/824c2bf26c2fad94?q=recursive+delete+T-SQL&_done=%2Fgroups%3Fq%3Drecursive+delete+T-SQL%26start%3D0%26hl%3Den%26lr%3D%26&_doneTitle=Back+to+Search&&d#824c2bf26c2fad94).
Като цяло обаче, смятам, че този (http://www.winnetmag.com/SQLServer/Forums/messageview.cfm?catid=1666&threadid=116492) подход също е доста добър. В частност той използва променливи от тип table, които също се съхраняват в tempDB.

Въпрос: Как да направя полето ID, което е цяло число автоматично да се увеличава при добавяне на нов запис?
Отговор: Използвай AutoNumber (в MS Access) или Identity (в MS SQL Server). За да извлечеш автоматично-генерираният primary key, виж слайда със заглавие "Първичен ключ – извличане" в лекцията за ADO.NET - там е описано как се прави - извиква се "SELECT @@IDENTITY".


Въпрос: Мога ли да достъпя една стойност от базата данни, или всеки път трябва да работя с таблици?


Отговор: Може да се достъпи една стойност чрез SqlCommand. Върнатата стойност от ExecuteScalar() задължително трябва да се преобразува към очакваният тип:

SqlCommand ordersCMD = new SqlCommand("SELECT Count(*) FROM Authors", nwindConn);

Int32 count = (Int32)ordersCMD.ExecuteScalar();

Това е примерна in-line заявка


Ето и пример за записана процедура, която връща единствена стойност:

CREATE PROC usp_InsertAuthor


(
@au_fname varchar(50),
@au_lname varchar(50)
)
AS

INSERT Authors (au_fname, au_lname, active)


VALUES (@au_fname, @au_lname, 1)

SELECT @@identity

GO


Въпрос:  Използвам следната SQL заявка за добавяне на запис:

insert [Table] values (@UserID,@ImageID,@Hyperlink,@Type,@RemainingShow)

Където Table има Primary Key TableID, който се увеличава автоматично с единица. Въпроса ми е как мога да разбера стойността на TableID за стойностите които се добавят.

Отговор: То автоматично се задава на променливата @@Identity. Можеш да използваш нея след INSERT.


Въпрос: Какво точно трябва да съдържа Connection string-a за връзка с базата данни?

Отговор: При MS SQL Server база от данни можеш да ползваш нещо такова:

SqlConnection dbConn = new SqlConnection(@"server=localhost; database=Northwind; Integrated Security=SSPI; Persist Security Info=false");



При MS Access база данни можеш да ползваш нещо такова:

OleDbConnection dbConn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\photos.mdb;Persist Security Info=False");


База данных защищена авторским правом ©obuch.info 2016
отнасят до администрацията

    Начална страница