This setting in Internet Explorer’s Internet Options solved my problem:
These are the steps to apply the gitignore file later:
git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
git push
My custom TimeTagHelper:
[HtmlTargetElement("time")]
public class TimeTagHelper : TagHelper
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.Content.SetHtmlContent($"<h1>{DateTime.Now.ToShortTimeString()}</h1>");
}
}
If I start the website project directly, the TagHelper works without problems. Launched from the Console / Service, the <time> tag was not replaced. Obviously the _ViewImports.cshtml is not loaded.
These are the steps that helped me:
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*;Views\**\*;Areas\**\Views" />
</ItemGroup>
PreserveCompilationContext
property to the PropertyGroup in Selhosted.Website.csproj<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>SelfHosted.Website</AssemblyName>
<RootNamespace>SelfHosted.Website</RootNamespace>
<TypeScriptToolsVersion>2.3</TypeScriptToolsVersion>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
You can find the sample project in my GitHub Repo: roeb/DotNetCoreSamples
]]>Hierbei gibt es einige Besonderheiten zu beachten, auf welche ich in diesem Post gern näher eingehen möchte.
Folgende Technologien kommen zum Einsatz:
Zu finden ist dieses Beispiel auf GitHub.
Die Konsolenapplikation kann als WindowsService oder direkt ausgeführt werden und hostet die Website und die API. Die Website und die API sind beides .NETStandard 2.0 Projekte, während die Console eine .NET Core 2.0 Anwendung darstellt.
IApplication definiert ein Interface zum Starten und Stoppen der Applikationen. Eine Applikation kann eine Website oder eine WebApi sein.
Diese Applikationen werden in Autofac registriert und einem gekapselten MicroService geladen und gestartet.
public class SelfHostedWindowService : MicroService, IMicroService
{
private IServiceProvider _provider;
public void Start()
{
this.StartBase();
var builder = new ContainerBuilder();
builder.RegisterType<WebApplication>().As<IApplication>();
builder.RegisterType<WebApiApplication>().As<IApplication>();
var applicationContainer = builder.Build();
_provider = new AutofacServiceProvider(applicationContainer);
foreach (var app in _provider.GetServices<IApplication>())
{
app.Start();
}
System.Console.WriteLine("Windows services started.");
}
public void Stop()
{
this.StopBase();
foreach (var app in _provider.GetServices<IApplication>())
{
app.Stop();
}
System.Console.WriteLine("Windows services stopped.");
}
}
Beim Starten der Konsole oder des Services, wird der MicroService registriert und in einer ServiceFactory geladen. Dadurch starten alle Applikationen, welche in den jeweiligen MicroService definiert sind.
ServiceRunner<SelfHostedWindowService>.Run(config =>
{
var serviceName = "SelfHosted.WindowsService";
config.SetName(serviceName);
config.Service(serviceConfig =>
{
serviceConfig.ServiceFactory((service, extraArguments) =>
{
return new SelfHostedWindowService();
});
serviceConfig.OnStart((service, extraArguments) =>
{
System.Console.WriteLine("Service {0} started", serviceName);
service.Start();
});
serviceConfig.OnStop((service) =>
{
System.Console.WriteLine("Service {0} stopped", serviceName);
service.Stop();
});
serviceConfig.OnError(e =>
{
System.Console.WriteLine($"Service '{serviceName}' errored with exception : {e.Message}");
});
});
});
Es gibt jedoch beim hosten seiner ASP.NET Core 2.0 Website in einer Console noch drei wichtige Dinge zu beachten.
public static RazorViewEngineOptions AddViews(this RazorViewEngineOptions options)
{
options.FileProviders.Add(new EmbeddedFileProvider(typeof(ServiceCollectionExtensions).GetTypeInfo().Assembly, "SelfHosted.Website"));
return options;
}
2. Danach stellte sich heraus, dass noch einige Assemblies fehlten. Diese werden ebenfalls per Extension Methode im Startup geladen.
public static RazorViewEngineOptions AddCompilationAssemblies(this RazorViewEngineOptions options)
{
var myAssemblies = AppDomain
.CurrentDomain
.GetAssemblies()
.Where(x => !x.IsDynamic)
.Concat(new[] { // additional assemblies used in Razor pages:
typeof(HtmlString).Assembly, // Microsoft.AspNetCore.Html.Abstractions
typeof(IViewLocalizer).Assembly, // Microsoft.AspNetCore.Mvc.Localization
typeof(IRequestCultureFeature).Assembly // Microsoft.AspNetCore.Localization
})
.Select(x => MetadataReference.CreateFromFile(x.Location))
.ToArray();
var previous = options.CompilationCallback;
options.CompilationCallback = context =>
{
previous?.Invoke(context);
context.Compilation = context.Compilation.AddReferences(myAssemblies);
};
return options;
}
public static IServiceCollection AddStaticFiles(this IServiceCollection collection)
{
// static files are embedded resources in the "wwwroot" folder
collection.Configure<StaticFileOptions>(options =>
{
options.FileProvider = new EmbeddedFileProvider(typeof(Startup).Assembly, typeof(Startup).Namespace + ".wwwroot");
});
return collection;
}
Aufgerufen werden die Extension Methods im Startup der Website, in der Funktion ConfigureServices wie folgt:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.AddMvc()
.AddRazorOptions(options =>
{
options.AddViews();
options.AddCompilationAssemblies();
});
services.AddStaticFiles();
var builder = new ContainerBuilder();
builder.Populate(services);
this.ApplicationContainer = builder.Build();
return new AutofacServiceProvider(this.ApplicationContainer);
}
Auf diesem Weg erreicht man eine sehr leichtgewichtige Anwendung, welche komplett in einem eigenen Prozess unabhängig von dem Betriebssystem und Webserver installiert werden kann. Somit erreicht man bei seiner Produktentwicklung, welchen bei Kunden vor Ort installiert werden muss, eine sehr hohe Flexibilität und ich unabhängig der Umgebung.
]]>So wendet man EOMONTH an, um sich den letzten Tag des Monats August im Jahr 2012 ausgegeben zu lassen:
Man kann jedoch auch Monat dazu addieren oder abziehen. Hierfür steht ein optionaler Operator zur Verfügung.
Es ist nur eine kleiner Erweiterung, aber sie erleichtert doch auf angenehme Art die Arbeit mit TSQL.
]]>Dieser ist jedoch leider bei Visual Studio 2012 nicht vorhanden. Hier führt es auch nicht zum gewünschten Erfolg, wenn man das aktuelle Azure SDK installiert. Jedoch ist es über einen Umweg möglich die vermisste Funktionalität in Visual Studio 2012 wieder herbei zu zaubern.
Im Hauptmenu von Visual Studio 2012 im Eintrag “Tools” auf den Menupunkt “Extensions and Updates …” klicken.
In dem sich nun öffnenden Fenster im linken Menu die Kategorie “Online” auswählen und in das Suchfeld “Identity” eingeben. Danach die “Identity and Access Tools” herunterladen und installieren und Visual Studio 2012 neustarten.
Nach dem Neustart von Visual Studio 2012 gibt es einen neuen Menueintrag im Kontextmenu des Projektes mit der Bezeichnung “Identity and Access …”. Hier kann nun wie gewohnt eine ACS Referenz hinzugefügt werden.
Würde die Suche auf einer Website ein Trefferergebnis von 400 Datensätzen betragen, möchte der Nutzer sicherlich nicht alle 400 Datensätze mit einmal auf der Website sehen, sondern z.B. immer nur 20 Stück. Diese 20 Datensätze werden jetzt auf 20 Seiten aufgelistet. Damit der Traffic möglichst gering bleibt, werden auch immer nur die Datensätze der aktuellen Seite geladen. Das nennt man Paging.
Mit dem SQL Server 2012 kommen unter anderen zwei neue Befehle welche in der ORDER BY Klausel genutzt werden können:
OFFSET
Legt fest wie viele Datensätze übersprungen werden, bevor Datensätze zurückgegeben werden.
FETCH
Gibt an wie viele Datensätze nach der OFFSET Klausel angezeigt werden sollen
In dem Beispiel werden Kundendaten selektiert, welche mit dem Nachnamen Meyer beginnen. Allerdings werden die ersten 40 Zeilen übersprungen und von da an 20 Zeilen selektiert.
Anstelle von NEXT kann man auch FIRST genutzt werden, es handelt sich hierbei nur um ein Synonym. Das gleich gilt für das Wort ROWS, hier kann auch ROW genutzt werden. Anstelle der direkten Anzahl der Datensätze bei OFFSET oder FETCH kann hier auch eine Variable zum Einsatz kommen. Dies könnte zum Beispiel so aussehen und wäre im zusammenhangen mit dynamisches Stored Procedures recht interessant.
Es ist ebenfalls möglich Expressions im Zusammenhang von OFFSET und FETCH zu nutzen. Hier ein Beispiel:
Zur Verfügung stehen die Erweiterungen OFFSET und FETCH bereits ab dem SQL Server 2012 Express.
]]>Herunterladen kann man sich SharePoint 2013 Foundation kostenlos auf der Seite von Microsoft. Wer eine MSDN Subscription besitzt, kann sich die größeren Versionen dort herunterladen.
Viel Spaß beim Ausprobieren!
]]>Der erste Lösungsansatz bei diesem Problem ist ein eingeschränkter Update Befehl auf 1000 Zeilen. Diese kann man mit einem UPDATE TOP (1000) und ebenso mit dem Befehl SET ROWCOUNT 1000 erreichen (Siehe Beispiele).
Möchte man nun etwa 100000 Zeilen aktualisieren empfiehlt es sich hierfür eine Schleife zu bauen. Außerdem sollte nach jedem Updatebefehl eine Wartezeit von 1-3 Sekunden eingefügt werden, damit andere Anfragen die Möglichkeit haben Sperren zu setzen. Dies erreicht man durch den Befehl WAITFOR DELAY. Hier ein Beispiel:
Der gesamte Updatevorgang kann dadurch etwas länger dauern, man minimiert jedoch die Wahrscheinlichkeit von Locks über die ganze Tabelle und erlaubt z.B. Triggern optimaler zu arbeiten.
]]>