Przygotowując się do głębszego zagłębienia się w temat ASP.NET MVC robię sobie powtórkę z starszego materiału, tj. asp.net oraz bazy danych. A skoro już jesteśmy przy temacie baz danych, to wypadało by wspomnieć m.in. o indeksach oraz ich typach występujących w bazie danych MS SQL.
Indeksy bazodanowe, podobnie jak indeksy w książkach służą do szybszego wyszukiwania interesujących nas informacji,
dzięki czemu zdecydowanie zwiększają szybkość wyszukiwania danych z
bazy danych, ale nieznacznie zwiększają czas zapisu/modyfikacji/usuwania danych, dlatego nie należy umieszczać ich ponad miarę. Indeks może zawierać maksymalnie 16 kolumn.
W bazie MS SQL występują dwa typy indeksów:
- indeks klastrowany (clustered index)
- indeks zwykły (non-clustered index)
Index klastrowany odpowiada za fizyczną reprezentację danych w bazie danych (fizyczny zapis danych na dysku twardym) oraz może być tylko jeden (dane mogą być poprawnie posortowane w strukturze B-drzewa tylko na jeden sposób). Każda operacja typu insert/update/delete na danych, na których jest założony index klastrowany powoduje fizyczne sortowanie B-drzewa z danymi.
Indeks zwykły (nieklastrowany) jest osobną strukturą danych, składowanych osobnie i posiadającym 'wartość' oraz wskaźnik do fizycznych danych które reprezentuje. Indeks zwykły, jeżeli tylko może wykorzystuje index klastrowany, aby zwiększyć efektywność przeszukiwania. W przypadku operacji insert/update/delete na danych, wartości indeksów zwykłych są aktualizowane. Na tabeli może być wiele indeksów zwykłych.
Przykład współdziałania indeksów dość dobrze wyjaśnia
niedziela, 14 lipca 2013
Control State vs View State
Jak powszechnie wiadomo, aplikacje napisane w asp.net są bez stanowe, a wywołanie każdego postbacka (np. za pomocą naciśnięcia przycisku) powoduje usunięcie aktualnej strony i utworzenie nowej. Aby zachować informacje pomiędzy postbackami stosuje się m.in. mechanizmy 'Control state' oraz 'View state'. A jakie są pomiędzy nimi główne różnice?
a) View state można wyłączyć (jeżeli inny developer korzysta z Twoich kontrolek, to może wyłączyć w nich 'view state', przez co kontrolki przestaną działać).
b) Control state nie da się wyłączyć (jest zawsze włączony), ale posiada ograniczenie co do ilości danych, jakie można w nim składować (nigdy nie próbujcie składować 'Grid View' w Control State).
Linki:
'Control state vs View State' na forum asp.net
'Control state vs View State' na forum stackoverflow
a) View state można wyłączyć (jeżeli inny developer korzysta z Twoich kontrolek, to może wyłączyć w nich 'view state', przez co kontrolki przestaną działać).
b) Control state nie da się wyłączyć (jest zawsze włączony), ale posiada ograniczenie co do ilości danych, jakie można w nim składować (nigdy nie próbujcie składować 'Grid View' w Control State).
Linki:
'Control state vs View State' na forum asp.net
'Control state vs View State' na forum stackoverflow
sobota, 6 lipca 2013
LoggingService, czyli logowanie błędów w Sharepoint 2010
W pracy programisty bardzo ważne jest logowanie błędów. Gorsze od nie
logowania błędów jest tylko błędne logowanie błędów (np. poprzez
napisanie własnego logera, co niestety miałem już okazję widzieć w
praktyce). Aby poprawnie logować błędy, najlepiej użyć jakiegoś gotowego
rozwiązania.
W przypadku aplikacji typu sharepoint nie powinniśmy używać zewnętrznych bibliotek. Jak opisuje to avishnyakov za pomocą spdevlab.com:
Dlatego w rozwiązaniach typu sharepoint 2010 dużo lepszym rozwiązaniem jest napisanie/skopiowanie klasy LoggingService dziedziczącej po SPDiagnosticsServiceBase.
Takie rozwiązanie znajdziemy w wielu miejscach w sieci, więc wydaje się ono być najlepsze.
Sama klasa, wygląda następująco:
Przydatne linki:
wpis Avishnyakov'a na spdevlab.com
wpis na blogu Waldka Mastykarza
wpis na blogu Jurgena Baurle
W przypadku aplikacji typu sharepoint nie powinniśmy używać zewnętrznych bibliotek. Jak opisuje to avishnyakov za pomocą spdevlab.com:
Suggestion #0 – Do not use 3rd part logging framework
Even if you stick to log4net, NLog, EventLog or System.Diagnostic.Trace, or trying to invent your own wheel, then DO NOT EVER USE THAT STUFF AGAIN.
SharePoint has its own logging system called “Unified Logging System (ULS)“. If you still wonder why would you use ULS instead your lovely logging framework, then consider the following facts:
- ULS is used by SharePoint, so if you used 3rd part logging, you would need to consolidate logs from few different sources
- ULS can be easily configured from Central Administration as well as by PowerShell
- ULS can write to Windows Event Log without elevated privileges (!)
- ULS shrinks text log files on the hard drives (!)
- ULS does not require web.config changes/modifications (!). That’s quite important concern for multi-server farm
- SharePoint can aggregate ULS log (and not just logs..) from multiple servers to the logging data base (Usage and Health Data Collection Service Application)
Dlatego w rozwiązaniach typu sharepoint 2010 dużo lepszym rozwiązaniem jest napisanie/skopiowanie klasy LoggingService dziedziczącej po SPDiagnosticsServiceBase.
Takie rozwiązanie znajdziemy w wielu miejscach w sieci, więc wydaje się ono być najlepsze.
Sama klasa, wygląda następująco:
natomiast jej użycie wygląda tak:public
class
LoggingService : SPDiagnosticsServiceBase
{
public
static
string
DiagnosticAreaName =
"My"
;
private
static
LoggingService _Current;
public
static
LoggingService Current
{
get
{
if
(_Current ==
null
)
{
_Current =
new
LoggingService();
}
return
_Current;
}
}
private
LoggingService()
:
base
(
"My Logging Service"
, SPFarm.Local)
{
}
protected
override
IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
List<SPDiagnosticsArea> areas =
new
List<SPDiagnosticsArea>
{
new
SPDiagnosticsArea(DiagnosticAreaName,
new
List<SPDiagnosticsCategory>
{
new
SPDiagnosticsCategory(
"WebParts"
, TraceSeverity.Unexpected, EventSeverity.Error)
})
};
return
areas;
}
public
static
void
LogError(
string
categoryName,
string
errorMessage)
{
SPDiagnosticsCategory category = LoggingService.Current.Areas[DiagnosticAreaName].Categories[categoryName];
LoggingService.Current.WriteTrace(0, category, TraceSeverity.Unexpected, errorMessage);
}
}
Do przeglądania logów polecam program ULSViewer dostępny na mocy licencji MICROSOFT PUBLIC LICENSE (Ms-PL)LoggingService.LogError(
"WebParts"
, ex.ToString);
Przydatne linki:
wpis Avishnyakov'a na spdevlab.com
wpis na blogu Waldka Mastykarza
wpis na blogu Jurgena Baurle
Log4net, czyli logowanie błędów w .NET
W pracy programisty bardzo ważne jest logowanie błędów. Gorsze od nie logowania błędów jest tylko błędne logowanie błędów (np. poprzez napisanie własnego logera, co niestety miałem już okazję widzieć w praktyce). Aby poprawnie logować błędy, najlepiej użyć jakiegoś gotowego rozwiązania.
Dla aplikacji typu '.net' np. asp.net (ale z wyłączeniem aplikacji typu sharepoint) jednym z gotowych, darmowych rozwiązań jest biblioteka log4net. Biblioteka dostępna jest pod licencją apache 2.0 (link do wikipedii).
Początkowo myślałem, aby się rozpisywać, jak skonfigurować oraz obsługiwać tą bibliotekę, ale myślę, że inni zrobili to znacznie lepiej, więc odsyłam do linków:
Łukasz Gąsior - > log4net-logujemy-zdarzenia-w-aplikacji/
Codeproject.com - log4net-Tutorial
Log4net - manual introduction
Przykładowa konfiguracja:
- web.config
-global.asax:
In application:
use:
Dla aplikacji typu '.net' np. asp.net (ale z wyłączeniem aplikacji typu sharepoint) jednym z gotowych, darmowych rozwiązań jest biblioteka log4net. Biblioteka dostępna jest pod licencją apache 2.0 (link do wikipedii).
Początkowo myślałem, aby się rozpisywać, jak skonfigurować oraz obsługiwać tą bibliotekę, ale myślę, że inni zrobili to znacznie lepiej, więc odsyłam do linków:
Łukasz Gąsior - > log4net-logujemy-zdarzenia-w-aplikacji/
Codeproject.com - log4net-Tutorial
Log4net - manual introduction
Przykładowa konfiguracja:
- web.config
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.
ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken= b77a5c561934e089" >
<section name="test.Properties.Settings" type="System.Configuration. ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken= b77a5c561934e089" requirePermission="false" />
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHan dler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG"/>
<appender-ref ref="LogFileAppender"/>
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\dev\test\test\Logs\test_log.log"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<datePattern value="dd.MM.yyyy" />
<staticLogFileName value="true" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="5MB" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %type.%method - %message%newline"/>
</layout>
</appender>
</log4net>
-global.asax:
protected void Application_Start(object sender, EventArgs e)
{
log4net.Config.
XmlConfigurator.Configure();
}
In application:
protected static readonly ILog log = LogManager.GetLogger(System.
Reflection.MethodBase. GetCurrentMethod(). DeclaringType);
use:
log.Info("foo bar");
piątek, 5 lipca 2013
T-SQL select po kilku ostatnich znakach
Często zdarza nam się konieczność pisania zapytania typu 'select' po ciągach znaków, typu varchar. Czasami potrzebujemy wyszukiwać lub wyświetlać wyniki tylko po części wyrazu. Wtedy najczęściej wystarczy funkcja SUBSTRING. A co, jeśli potrzebujemy wyszukać część wyrazu po kilku ost. znakach (np. dane, które posiadamy są różnej długości*)?? Wtedy z pomocą przychodzi nam funkcja RIGHT
* - przykład 'życiowy'. Dane, które przychodzą z jednego, z zewnętrznych syst. informatycznych, z którym się integrujemy czasami przychodzą w formacie '0000xxx' (np. 0000123), a innym razem jako 'xxx' (np. '123').
SELECT RIGHT(column, 3)
* - przykład 'życiowy'. Dane, które przychodzą z jednego, z zewnętrznych syst. informatycznych, z którym się integrujemy czasami przychodzą w formacie '0000xxx' (np. 0000123), a innym razem jako 'xxx' (np. '123').
DevExpress AspxGridView filtrowanie w zakresie dat/liczb od-do
O ile standardowy devexpress aspxgridview nie posiada domyślnie wbudowanego filtru wyboru daty w zakresie od-do (standardowo można wybrać datę z kalendarzyka w 'popupie', lub z góry zdefiniowane wartości 'przedziału' jako 'drop down list') to od czego mamy support i genialne wręcz możliwości rozszerzania domyślnej funkcjonalności jakie oferują nam kontrolki devexpressa.
Zakres filtrów z datami 'od-do' został opisany w tym oto zgłoszeniu supportu, natomiast utworzenie odpowiedniego filtru dla wartości numerycznych jest bliźniaczo podobne poprzez utworzenie klasy
Zakres filtrów z datami 'od-do' został opisany w tym oto zgłoszeniu supportu, natomiast utworzenie odpowiedniego filtru dla wartości numerycznych jest bliźniaczo podobne poprzez utworzenie klasy
NumericSelector
, która jest klasą bliźniaczą klasy DateSelector.
środa, 26 czerwca 2013
Usuwanie elementu kolekcji podczas iterowania po tej kolekcji.
Kolekcje dynamiczne w jakie wyposażone są języki c# oraz java to wielki krok na przód w porównaniu do standardowego języka c++. Oczywiście w c++ były tablice i wskaźniki, a rozszerzeniach języka c++ kolekcje, jednak operowanie na dynamicznych listach z punktu widzenia programisty jest dużo bardziej wygodne i bezpieczne na kolekcjach niż na tablicach (ehh, te wskaźniki). Główna zaleta kolekcji polega bowiem na tym, że dynamicznie zmieniają one swoją objętość podczas dodawania i usuwania elementów. Takie zachowanie ma mnóstwo plusów, ale ma też jeden minus, tj. jeżeli iterujemy pętlą po kolekcji generycznej w standardowy sposób (od elementu 0, do elementu n) to usuwając elementy z listy, dynamicznie zmniejszamy jej wielkość, a co za tym idzie pętla będzie próbowała się odwołać do większej ilości elementów niż jest w kolekcji, a to spowoduje wystąpienie wyjątku. Oczywiście jest na to prosty i wygodny sposób, tj. iterowanie po kolekcji 'od tyłu'. Rozwiązanie zaczerpnięte z forum stackoverflow.com
var list = new List<int>(Enumerable.Range(1, 10)); for (int i = list.Count - 1; i >= 0; i--) { if (list[i] > 5) list.RemoveAt(i); } list.ForEach(i => Console.WriteLine(i));
Subskrybuj:
Posty (Atom)