wtorek, 30 lipca 2013

Entity Framework Modified State (updating row values)

Pogłębiając moją wiedzę nt. Entity Framework zauważyłem pewną ciekawą właściwość, mianowicie w syt. gdy tylko niektóre kolumny w wierszu z danymi zostały zaktualizowane, to Entity Framework zachowuje się w różny sposób dla różnego rodzaju aplikacji:
- dla aplikacji okienkowych (windows forms) aktualizuje tylko wybrane kolumny danego rekordu
- dla aplikacji webowych (asp) aktualizuje wszystkie kolumny danego rekordu


In a desktop application, state changes are typically set automatically. In this type of application, you read an entity and make changes to some of its property values. This causes its entity state to automatically be changed to Modified. Then when you call SaveChanges, the Entity Framework generates a SQL UPDATE statement that updates only the actual properties that you changed.
However, in a web application this sequence is interrupted, because the database context instance that reads an entity is disposed after a page is rendered. When the HttpPost Edit action method is called, this is the result of a new request and you have a new instance of the context, so you have to manually set the entity state to Modified. Then when you call SaveChanges, the Entity Framework updates all columns of the database row, because the context has no way to know which properties you changed.
If you want the SQL Update statement to update only the fields that the user actually changed, you can save the original values in some way (such as hidden fields) so that they are available when the HttpPost Edit method is called. Then you can create a Student entity using the original values, call the Attach method with that original version of the entity, update the entity's values to the new values, and then call SaveChanges. For more information, see Add/Attach and Entity States and Local Data on the Entity Framework team blog.
 źródło

niedziela, 28 lipca 2013

Log in as a different user in sharepoint 2013

Ten konkretny wpis, to zwykły link do innego bloga, ale zostawiam to tutaj, ponieważ ten blog jest również moim prywatnym notatnikiem.

heblobfarm.wordpress.com <-> sharepoint-2013-ui-log-in-as-a-different-user/

Layouts folder location in sharepoint 2010/2013

No i stało. Oficjalnie wyszedł długo oczekiwany następca sharepointa 2010, czyli sharepoint 2013. Zapewne posiada wiele ciekawych funkcji i udogodnień, natomiast pierwszą rzeczą, która rzuca się w oczy, to fakt, że projekty napisane w sharepoint 2010, które planujemy wdrożyć dla sharepointa 2013 powinny być skonwertowane na typ projektu 'sharepoint 2013'. Projekt po takiej konwersji nie może zostać użyty w 'sharepoint 2010'. W praktyce jesteśmy więc zmuszeni do stworzenia dwóch projektów obok siebie i wymuszenia, aby oba projekty posiadały wspólne pliki .cs (niestety, ale inne pliki, czyli aspx, ascx, css, js, xml, png, i cała reszta plików umieszczana zazwyczaj w 'layouts' musi być zdublowana i znajdować się w obu projektach).

Gdyby jednak tego było mało, to folder layouts w nowym sharepoincie nie nazywa się 'layouts/' (tak jak to było w sharepoint 2010), tylko... 'layouts/15/".
Na szczęście jest sposób, aby można było wykorzystywać te same pliki .cs w obu projektach. Oto on, czyli klasa UrlHelper:

  public class UrlHelper
    {

        public static string LayoutsUrl
        {
            get
            {
                PropertyInfo pi = typeof(SPUtility).GetProperty(
"ContextLayoutsFolder", BindingFlags.Public | BindingFlags.Static);
                if (pi == null)
                    return "/_layouts/";
                else
                    return String.Format("/{0}/", pi.GetValue(null, null).ToString());
            }
        }

        public static string ImagesUrl
        {
            get
            {
                PropertyInfo pi = typeof(SPUtility).GetProperty("ContextImagesRoot", BindingFlags.Public | BindingFlags.Static);
                if (pi == null)
                    return "/_layouts/images/";
                else
                    return String.Format("{0}", pi.GetValue(null, null).ToString());
            }
        }


        public static string ControlTemplatesUrl
        {
            get
            {
                PropertyInfo pi = typeof(SPUtility).GetProperty("ContextControlTemplatesFolder", BindingFlags.Public | BindingFlags.Static);
                if (pi == null)
                    return "/_CONTROLTEMPLATES/";
                else
                    return String.Format("/{0}/", pi.GetValue(null, null).ToString());

            }
           
        }
    }

W praktyce, wszędzie, gdzie odwołujemy się do katalogów związanych z 'layouts', zamiast wpisywać stringi, powinniśmy wykorzystać metodę klasy UrlHelper.

poniedziałek, 22 lipca 2013

Selenium - software testing framework for web applications

Przeglądając wykład Grzegorza Dudy podczas konferencji confitura 2012 pt. From Busy to Effective Developer odkryłem fajne, nowe narzędzie, które zademonstrował Grzegorz. Narzędzie nazywa się selenium i służy do testowania stron internetowych. O ile, nie wgłębiałem się szczegółowo w API tego narzędzia, to jego podstawowa funkcjonalność, dostępna jako plug-in do przeglądardki firefox służy do nagrywania/reprodukcji schematu poruszania się po stronie internetowej.

Czasami zdarza się bowiem, że aby odtworzyć błąd, trzeba się 'przeklikać' przez wiele formularzy (i dopiero wtedy podpiąć debugger). W takich właśnie momentach przydaje się Selenium. Za pierwszym razem, przeklikując się przez formularze włączamy opcję 'rejestrowania', a przy nast., okazji, gdy potrzebujemy wykonać identyczną operację tylko włączamy opcję odtwarzania poprzednio zapisanego scenariusza testowego.

Narzędzie dostępne jest na licencji Apache 2.0 więc spokojnie możemy z niego korzystać, a nawet rozwijać.

niedziela, 21 lipca 2013

Programming never changes (asp mvc)

Czyli... w końcu rozpocząłem moją przygodę z ASP MVC na poważnie. Rozpocząłem ją od wszelkiej maści tutoriali, jakie można znaleźć na oficjalnej stronie asp mvc. O ile pierwszy tutorial z asp mvc 4 (MvcMovie) poszedł gładko, to już w nast. z asp mvc 3 (MvcMusicStorew 5 części tutka wystąpiły błędy, a dokładniej "Using the same DbCompiledModel to create contexts against different types of database servers is not supported". Ale... od czego mamy stackoverflow.com ;)

Parafrazując słynny cytat z serii Fallout: Programming never changes

niedziela, 14 lipca 2013

Index oraz Index Klastrowany (Clustered Index)

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





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

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:


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:
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);
 }
}
natomiast jej użycie wygląda tak:

LoggingService.LogError("WebParts", ex.ToString);
Do przeglądania logów polecam program ULSViewer dostępny na mocy licencji  MICROSOFT PUBLIC LICENSE (Ms-PL)

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
    <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.Log4NetConfigurationSectionHandler,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

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
NumericSelector , która jest klasą bliźniaczą klasy DateSelector.