Tworzenie paczek NuGet
W skrócie opisze jak tworzyć paczki nuget bezpośrednio z projektu VS.
Wszystkie polecenia będziemy wykonywać narzędziem nuget.exe
Tworzenie paczki release
W folderze z projektem (plik .csporj) uruchamiamy
nuget spec
Po uruchomieniu zostanie utworzony specjalny plik .nuspec o takiej samej nazwie jak nazwa projektu. Plik ten zawiera meta informację na temat paczki.
[xml]
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>My project release notes</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>tag1 tag2</tags>
</metadata>
</package>
[/xml]
Dane w formacie $xyz$ oznaczają że te informacje są pobierane z pliku dll.
Gdy plik nuspec mamy już gotowy to budujemy projekt i tworzymy paczkę uruchamiając polecenie:
nuget pack MyProject.csproj
Jeśli chcemy dodać zależne biblioteki to dodajemy parametr IncludeReferencedProjects
nuget pack MyProject.csproj -IncludeReferencedProjects -Prop Configuration=Release
Jeśli paczka się utworzy to wysyłamy ją na serwer poleceniem:
nuget push MyProject.1.0.0.nupkg -s http://yourdomain.com/nuget API_KEY
Tworzenie paczki prerelease
Jeśłi paczkę tworzymy z pliku projektu (.csproj lub .vbproj) to utworzenie paczki prelese ogranicza się do dodania atrybutu AssemblyInformationalVersionAttribute i określeniu wersji:
[assembly: AssemblyInformationalVersion("1.0.1-alpha")]
NuGet użyje tej wartości zamiast danych z AssemblyVersion.
Więcej informacji
Własny serwer NuGet
Każdy kto korzysta z VS wie co to NuGet i jak bardzo on upraszcza życie, dodawanie zewnętrznych bibliotek jest banalnie proste, aktualizacja do nowej wersji – jedno kliknięcie i gotowe. A co jeśli taki serwer możemy sobie sami postawić. O ile prostsze było by współdzielenie bibliotek we własnych projektach. Może w firmie której pracujecie dalej ręcznie podpinacie biblioteki, warto zaproponować postawienie takiego serwera – trwa to chwilę, a uprasza bardzo wiele.
Tworzenie własnego serwera
- Tworzymy pusty projekt ASP.NET Web Application (ASP.NET 4.x)
- Instalujemy paczkę NuGet.Server
- Wdrażamy aplikację na docelowy serwer
NuGet jest dostępy pod adresem http://yourdomain/nuget - Konfigurujemy i cieszymy się własnym serwerem NuGet
Konfiguracja
Konfiguracja to ustawienie odpowiednich wpisów w pliku web.config
Pierwsze co robimy to ustawienie klucza umożliwiającego wrzucanie paczek:
[xml]
<add key="apiKey" value="YOUR-API-KEY" />
[/xml]
Na czas testów możemy ustawić allowOverrideExistingPackageOnPush
na true, co może się przydać jak zaczniemy uczyć się tworzyć paszki i wrzucać je na serwer.
[xml] <add key="allowOverrideExistingPackageOnPush" value="false" /> [/xml]
Wrzucanie paczek
Paczki wrzucamy aplikacją nuget.exe z parametrem push:
[bash]
nuget push {packagefile} -s http://yourdomain/nuget {apikey}
[/bash]
Kunfiguracja VisualStudio
Aby paczki z naszego serwera były widoczne w VS musimy dodać go do listy Package Sources. Aby to zrobić w VS 2015 otwieramy okno dodawania źródeł dla nugeta: Tools -> NuGet Package Manager -> Package Manager Settings.
W otwartym oknie wybieramy Package Sources
Klikamy dodaj i uzupełniamy dane naszego serwera.
Po zatwierdzeniu nasz serwer jest już widoczny na liście:
Teraz już możemy instalować z niego paczki.
Podsumowanie
Jak widać instalacja i konfiguracja własnego serwera NuGet to tylko kilka minut, a korzyść bardzo wiele. Myślę że warto to wdrożyć dla swoich projektów jak również w firmie jeśli dalej ręcznie podpinacie zewnętrzne biblioteki.
Więcej informacji:
The Clean Architecture
Prezentacja wujka Boba na temat Clean Architecture
Główne założenia Clean Architecture
- Struktura projektu powinien odzwierciedlać architekturę, a nie użyty framework (Screaming Architecture).
- Elementy takie jak UI, serwer, baza danych, użyty ORM to szczegóły który powinny być ukryte
- Testowalność – reguły binzesowe można testować nieleżenie od UI, użytego serwera, bazy danych itd.
- Wykorzystanie Dependency Inversion principle
Więcej informacji:
Effective software delivery
Opis z YouTube: Podczas tej prezentacji przejdziemy przez poszczególne fazy dostarczania oprogramowania i odpowiemy sobie na pytanie jakie możliwości optymalizacji mamy do dyspozycji na poszczególnych etapach. Powiemy sobie jakich błędów unikać poczas prototypowania, jak wykorzystać specyfikę projektu i nie dać się ponieść pragnieniu rozwiązywania wszystkich problemów za pomocą złotego młotka. Poruszymy mit spowalniających development testów automatycznych, odpowiemy na pytanie czy DRY mówi tylko o unikaniu copy-paste w naszej aplikacji oraz przeanalizujemy szerzej zagadnienie przedwczesnej optymalizacji. Poznamy także narzędzia i techniki, która pozwalają nam efektywniej pracować nad wytwarzaniem oprogramowania.
Zasady dobrego programisty
Don’t Repeat Yourself (DRY) – nie powtarzaj się
Jest to jedna z najważniejszych zasad i powinniśmy traktować ją bardzo poważnie. Objawia się ona nie tylko powielaniem tego samego kodu i używanie metody Copy&Paste.
Single-Responsibility Principle (SRP) – zasada pojedynczej odpowiedzialności
Żadna klasa nie może być modyfikowana z więcej niż jednego powodu.
Jeśli jesteśmy w stanie wyobrazi sobie więcej niż jeden bodziec skłaniający programistę do zmiany klasy, mamy do czynienia z klasą rozciągającą się na więcej niż jeden obszar odpowiedzialności.*
Open/Close Principle (OCP) – zasada otwarte-zamknięte
Składniki oprogramowania (klasy, moduły, funkcje itp.) powinny być otwarte na rozbudowę, ale zamknięte dla modyfikacji.
Na początku może wydawać się to sprzeczne bo jak mamy wprowadzać zmiany skoro nie możemy modyfikować kodu. Odpowiedzią jest abstrakcja. W świecie obiektowym abstrakcje mają postać abstrakcyjnych klas bazowych, a grupa niezwiązanych, możliwych zastosowań jest reprezentowana przez klasy pochodne.
Moduł, który wykorzystuje abstrakcje, może być zamknięty dla modyfikacji, ponieważ jego działanie jest uzależnione właśnie od tej abstrakcji. Dzięki temu mamy możliwość rozszerzania tego modułu bez potrzeby modyfikacji jego kodu.
Liskov Substitution Principle (LSP) – zasada podstawień Liskov
Musi istnieć możliwość zastępowania typów bazowych ich podtypami.
Znaczenie tej zasady staje się oczywiste, kiedy rozważymy konsekwencje jej naruszenia. Przypuśćmy, że dysponujemy funkcją f, która otrzymuje za pośrednictwem swojego parametru referencję do pewnej klasy bazowej B. Załóżmy także, że przekazanie na wejściu funkcji referencji do klasy D (potomnej względem klasy B) powoduje błędne działanie tej funkcji. W takim przypadku klasa D narusza zasadę podstawienia Liskov (LSP). Oznacza to, że klasa D jest wrażliwa w kontekście funkcji f.
Prostym przykładem naruszenia tej zasady jest weryfikacja typów za pomocą instrukcji if-else
Dependecy-Inversion Principle (DIP) – zasada odwracania zależności
Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Obie grupy modułów powinny zależeć od abstrakcji.
Abstrakcje nie powinny zależeć od szczegółowych rozwiązań. To szczegółowe rozwiązania powinny zależeć od abstrakcji.
Interface Segregation Principle (ISP) – zasada segregacji interfejsów
Ma na celu wyeliminowanie nieporęcznych “grubych” interfejsów. Do tej grupy zaliczamy nadmiernie rozbudowane i niespójne interfejsy klas. Innymi słowy, interfejsy takich klas należy dzielić na mniejsze grupy metod. Każda taka grupa odpowiada za obsługę innego zbioru klientów. Oznacza to, że część klientów będzie korzystała z jednej grypy metod, podczas gdy pozostałe aplikacje klienckie będą korzystały z pozostałych grup metod.
Zasada skautów: Pozostaw obóz czyściejszym, niż go zastałeś.
(Staraj się pozostawić ten świat nieco lepszym niż go zastałeś)
Bibliografia:
- Agile Programowanie zminne, Robert C. Martin, Micah Martin
- Czysty kod, Robert C. Martin
The transaction log for db BizTalkMsgBoxDb is full.
SQL Server returned error string: “The transaction log for database ‘BizTalkMsgBoxDb’ is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases”.
Solution:
[sql]
sp_helpdb ‘BizTalkMsgBoxDb’
ALTER DATABASE BiztalkMsgBoxDb
SET RECOVERY SIMPLE;
GO
DBCC SHRINKFILE (BiztalkMsgBoxDb_log, 1);
GO
sp_helpdb ‘BizTalkMsgBoxDb’
GO
ALTER DATABASE BiztalkMsgBoxDb
SET RECOVERY FULL
GO
[/sql]
MSCRM 4.0 Web Service Toolkit (JavaScript)
CRM Web Service Toolkit jest małą JavaScript’ową biblioteką umożliwiającą łatwy dostęp do web serwisów Microsoft Dynamics CRM 4.0.
Dzięki niej możemy w szybki sposób:
- tworzć/aktualizować encje
- zmieniać stan encji
- tworzyć zapytania za pomocą fetchXML czy poprzez metodę RetrieveMultiple
- i wiele innych metod dostępnych w web serwisach CRMa
Przykłady
Encje tworzymy za pomocą metody CrmServiceToolkit.Create()
[js]
// Use CrmServiceToolkit. Create() to create a CRM contact record.
var contact = new CrmServiceToolkit.BusinessEntity("contact");
contact.attributes["firstname"] = "Diane";
contact.attributes["lastname"] = "Morgan";
contact.attributes["gendercode"] = 2;
contact.attributes["familystatuscode"] = 1; // Picklist : Single – 1
contact.attributes["creditlimit"] = 3000;
var createResponse = CrmServiceToolkit.Create(contact);
[/js]
CrmServiceToolkit.Retrieve() używamy do zwracania pojedynczych encji
[js]
// Use CrmServiceToolkit.Retrieve() to retrieve a CRM contact record.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var cols = ["firstname", "lastname", "familystatuscode", "creditlimit", "birthdate", "donotemail"];
var retrievedContact = CrmServiceToolkit.Retrieve("contact", contactId, cols);
alert(retrievedContact.getValue(‘lastname’));
alert(retrievedContact.getValue(‘firstname’));
// Picklist value (integer)
alert(retrievedContact.getValue(‘familystatuscode’));
// Picklist selected text
alert(retrievedContact.getValue(‘familystatuscode’, ‘name’));
// Currency field value
alert(retrievedContact.getValue(‘creditlimit’));
// Currency field formatted value (string)
alert(retrievedContact.getValue(‘creditlimit’, ‘formattedvalue’));
// Datetime field date/time value
alert(retrievedContact.getValue(‘birthdate’));
// Datetime field date string
alert(retrievedContact.getValue(‘birthdate’, ‘date’));
// Datetime field time string
alert(retrievedContact.getValue(‘birthdate’, ‘time’));
// Bit field value
alert(retrievedContact.getValueAsBoolean(‘donotemail’));
[/js]
Metoda CrmServiceToolkit.setState() umożliwia nam zmiane stany encji
[js]
// Use CrmServiceToolkit.setState() to update a CRM record status.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var response = CrmServiceToolkit.setState(‘contact’, contactId, ‘Inactive’, 2);
alert(response);
[/js]
CrmServiceToolkit.queryByAttribute() zwraca nam wszystkie rekordy spełniające podane kryterja.
[js]
// Use CrmServiceToolkit.queryByAttribute() to retrieve all CRM records that match the query criteria.
var queryOptions = {
entityName : "contact",
attributes : ["firstname", "lastname"], // Search by firstname and lastname
values : ["John", "Smith"], // Find all contacts whose firstname is John, lastname is Smith
columnSet : ["familystatuscode", "creditlimit", "birthdate"],
orderby : ["creditlimit", "birthdate"]
};
var fetchedContacts = CrmServiceToolkit.queryByAttribute(queryOptions);
[/js]
Więcej informacji na:
http://crmtoolkit.codeplex.com/
http://danielcai.blogspot.com/2010/07/crm-web-service-toolkit-for-javascript.html
MSCRM 4.0 Form Properties
Do pól formularza odwołujemy się poprzez obiekt crmForm:
[js]
crmForm.propertyname
[/js]
Tabelka poniżej przedstawia dostępne właściwości.
Właściwość | Typ | Opis |
IsDirty | bool | Określa czy formularz był modyfikowany |
FormType | int | Tylko do odczytu. Typ formularza.Możliwe wartości:
|
ObjectId | string | Tylko do odczytu. Identyfikator encji. Jeśli formularz jest w trybie edycji |
ObjectTypeCode | string | Tylko do odczytu. Kod typu encji którą edytujemy/wyświetlamy na formularzu |
ObjectTypeName | string | Tylko do odczytu. Nazwa typu encji której dotyczy formularz |
all.{field name} | Kolekcja poszczególnych pól formularza odpowiadającym polom w encji lub IFRAME formularza. |
Przykład
[js]
var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;
// Test the FormType and ObjectId properties.
switch (crmForm.FormType)
{
case CRM_FORM_TYPE_CREATE:
alert("This is a create form.");
break;
case CRM_FORM_TYPE_UPDATE:
alert("This is an update form, the ID is " + crmForm.ObjectId + ".");
break;
}
[/js]
[js]
var CRM_ENTITY_ACCOUNT = 1;
var CRM_ENTITY_CONTACT = 2;
// Test the ObjectTypeCode property.
switch (crmForm.ObjectTypeCode)
{
case CRM_ENTITY_ACCOUNT:
alert("This is an Account form.");
break;
case CRM_ENTITY_CONTACT:
alert("This is a Contact form.");
break;
}
[/js]
Żródło: http://msdn.microsoft.com/en-us/library/cc150873.aspx