اس کیوال سرور
الگوهای طراحی برنامه نویسی شیءگرا
امنیت
توسعه وب
دات نت فریم ورک
دبلیو اف
سی و مشتقات
کتابهای رایگان
لینوکس
متفرقه
محیطهای مجتمع توسعه
مسایل انسانی، اجتماعی و مدیریتی برنامه نویسی
ویندوز
PM> Install-Package Lex.Db
public class Product { public int Id { get; set; } public string Name { get; set; } } public class Customer { public int Id { get; set; } public string Name { get; set; } public string City { get; set; } } public class Order { public int Id { get; set; } public int? CustomerFK { get; set; } public int[] ProductsFK { get; set; } }
public static class Database { public static DbInstance Instance { get; private set; } public static DbTable<Product> Products { get; private set; } public static DbTable<Order> Orders { get; private set; } public static DbTable<Customer> Customers { get; private set; } /// <summary> /// سازنده استاتیکی که در طول عمر برنامه فقط یکبار اجرا میشود /// </summary> static Database() { createDb(); getTables(); } private static void getTables() { Products = Instance.Table<Product>(); Customers = Instance.Table<Customer>(); Orders = Instance.Table<Order>(); } private static void createDb() { Instance = new DbInstance(Path.Combine(Environment.CurrentDirectory, "LexDbTests")); Instance.Map<Product>() .WithIndex("NameIdx", x => x.Name) .Automap(i => i.Id, true); Instance.Map<Order>() .Automap(i => i.Id, true); Instance.Map<Customer>() .WithIndex("NameIdx", x => x.Name) .WithIndex("CityIdx", x => x.City) .Automap(i => i.Id, true); Instance.Initialize(); } }
private static void addData() { var customer1 = new Customer { Name = "customer1", City = "City1" }; var customer2 = new Customer { Name = "customer2", City = "City2" }; Database.Instance.Save(customer1, customer2); // automatic Id assignment after Save var product1 = new Product { Name = "product1" }; var product2 = new Product { Name = "product2" }; Database.Instance.Save(product1, product2); // automatic Id assignment after Save var order1 = new Order { CustomerFK = customer1.Id, ProductsFK = new[] { product1.Id } }; var order2 = new Order { CustomerFK = customer2.Id, ProductsFK = new[] { product1.Id, product2.Id } }; Database.Instance.Save(order1, order2); // automatic Id assignment after Save }
private static void loadAll() { var orders = Database.Orders.LoadAll(); foreach (var order in orders) { // نحوه دریافت اطلاعات مشتری بر اساس کلید خارجی ثبت شده var orderCustomer = Database.Customers.LoadByKey(order.CustomerFK.Value); Console.WriteLine("Order Id: {0}, Customer: {1} ({2}) {3}", order.Id, orderCustomer.Name, orderCustomer.Id, orderCustomer.City); // نحوه بازیابی لیستی از اشیاء مرتبط از طریق آرایهای از کلیدهای خارجی ثبت شده var orderProducts = Database.Products.LoadByKeys(order.ProductsFK); foreach (var product in orderProducts) { Console.WriteLine(" Product Id: {0}, Name: {1}", product.Id, product.Name); } } }
private static void queryingByAnIndex() { var name = "customer1"; var customersList = Database.Customers .IndexQueryByKey("NameIdx", name) .ToList(); foreach (var person in customersList) { Console.WriteLine(person.Name); } }
// Using Take and Skip var list1 = Database.Orders.Query<int>() // primary idx .Take(1).Skip(2).ToList(); // Querying Between Ranges var list2 = Database.Customers .IndexQuery<string>("NameIdx") .GreaterThan("a", orEqual: true).LessThan("d").ToList();
private static void deletingRecords() { Database.Customers.DeleteByKey(key: 1); var customers = Database.Customers.LoadByKeys(new[] { 1, 2 }); Database.Customers.Delete(customers); }
import React, { Component } from "react"; class TableHeader extends Component { raiseSort = path => { console.log("raiseSort", path); const sortColumn = { ...this.props.sortColumn }; if (sortColumn.path === path) { sortColumn.order = sortColumn.order === "asc" ? "desc" : "asc"; } else { sortColumn.path = path; sortColumn.order = "asc"; } this.props.onSort(sortColumn); }; render() { return ( <thead> <tr> {this.props.columns.map(column => ( <th onClick={() => this.raiseSort(column.path)}>{column.label}</th> ))} </tr> </thead> ); } } export default TableHeader;
import TableHeader from "./common/tableHeader";
columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, {}, {} ];
render() { const { movies, onDelete, onLike, onSort, sortColumn } = this.props; return ( <table className="table"> <TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort} /> <tbody>
index.js:1375 Warning: Each child in a list should have a unique "key" prop. Check the render method of `TableHeader`. See https://fb.me/react-warning-keys for more information.
class MoviesTable extends Component { columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, { key: "like" }, { key: "delete" } ];
render() { return ( <thead> <tr> {this.props.columns.map(column => ( <th key={column.path || column.key} style={{ cursor: "pointer" }} onClick={() => this.raiseSort(column.path)} > {column.label} </th> ))} </tr> </thead> );
import React, { Component } from "react"; class TableBody extends Component { render() { const { data, columns } = this.props; return ( <tbody> {data.map(item => ( <tr> {columns.map(column => ( <td></td> ))} </tr> ))} </tbody> ); } } export default TableBody;
{movies.map(movie => ( <tr key={movie._id}> <td>{movie.title}</td>
<td>{item[column.path]}</td>
getPropValue(obj, path) { if (!path) { return obj; } const properties = path.split("."); return this.getPropValue(obj[properties.shift()], properties.join(".")); }
<td>{getPropValue(item, column.path)}</td>
class MoviesTable extends Component { columns = [ { path: "title", label: "Title" }, { path: "genre.name", label: "Genre" }, { path: "numberInStock", label: "Stock" }, { path: "dailyRentalRate", label: "Rate" }, { key: "like", content: movie => ( <Like liked={movie.liked} onClick={() => this.props.onLike(movie)} /> ) }, { key: "delete", content: movie => ( <button onClick={() => this.props.onDelete(movie)} className="btn btn-danger btn-sm" > Delete </button> ) } ];
renderCell = (item, column) => { if (column.content) { return column.content(item); } return this.getPropValue(item, column.path); }; createKey = (item, column) => { return item._id + (column.path || column.key); }; render() { const { data, columns } = this.props; return ( <tbody> {data.map(item => ( <tr key={item._id}> {columns.map(column => ( <td key={this.createKey(item, column)}> {this.renderCell(item, column)} </td> ))} </tr> ))} </tbody> ); }
//... import TableBody from "./common/tableBody"; //... class MoviesTable extends Component { // ... render() { const { movies, onSort, sortColumn } = this.props; return ( <table className="table"> <TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort} /> <TableBody columns={this.columns} data={movies} /> </table> ); } }
renderSortIcon = column => { const { sortColumn } = this.props; if (column.path !== sortColumn.path) { return null; } if (sortColumn.order === "asc") { return <i className="fa fa-sort-asc" />; } return <i className="fa fa-sort-desc" />; };
{column.label} {this.renderSortIcon(column)}
import TableBody from "./tableBody"; import TableHeader from "./tableHeader";
import TableBody from "./tableBody"; import TableHeader from "./tableHeader"; class Table extends Component { render() { const { columns, sortColumn, onSort, data } = this.props; return ( <table className="table"> <TableHeader columns={columns} sortColumn={sortColumn} onSort={onSort} /> <TableBody columns={columns} data={data} /> </table> ); } } export default Table;
//... import Table from "./common/table"; class MoviesTable extends Component { //... render() { const { movies, onSort, sortColumn } = this.props; return ( <Table columns={this.columns} sortColumn={sortColumn} onSort={onSort} data={movies} /> ); } }
var guid = Guid.NewGuid();
var customer = connection.ExecuteMapperQuery<customer>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
var tbl = new Products();
var products = tbl.All(where: "CategoryID = @0 AND UnitPrice > @1", orderBy: "ProductName", limit: 20, args: 5,20);
<div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div>
using System; using System.Net.Http; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace BlazorWasmTelegramLogger.Client.Logging { public class ClientLoggerProvider : ILoggerProvider { private readonly HttpClient _httpClient; private readonly WebApiLoggerOptions _options; private readonly NavigationManager _navigationManager; public ClientLoggerProvider( IServiceProvider serviceProvider, IOptions<WebApiLoggerOptions> options, NavigationManager navigationManager) { if (serviceProvider is null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (options is null) { throw new ArgumentNullException(nameof(options)); } _httpClient = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<HttpClient>(); _options = options.Value; _navigationManager = navigationManager ?? throw new ArgumentNullException(nameof(navigationManager)); } public ILogger CreateLogger(string categoryName) { return new WebApiLogger(_httpClient, _options, _navigationManager); } public void Dispose() { } } }
using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public static class ClientLoggerProviderExtensions { public static ILoggingBuilder AddWebApiLogger(this ILoggingBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.AddSingleton<ILoggerProvider, ClientLoggerProvider>(); return builder; } } }
public ClientLoggerProvider( IServiceProvider serviceProvider, IOptions<WebApiLoggerOptions> options, NavigationManager navigationManager)
public ILogger CreateLogger(string categoryName) { return new WebApiLogger(_httpClient, _options, _navigationManager); }
using System; using System.Net.Http; using System.Net.Http.Json; using BlazorWasmTelegramLogger.Shared; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public class WebApiLogger : ILogger { private readonly WebApiLoggerOptions _options; private readonly HttpClient _httpClient; private readonly NavigationManager _navigationManager; public WebApiLogger(HttpClient httpClient, WebApiLoggerOptions options, NavigationManager navigationManager) { _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); _options = options ?? throw new ArgumentNullException(nameof(options)); _navigationManager = navigationManager ?? throw new ArgumentNullException(nameof(navigationManager)); } public IDisposable BeginScope<TState>(TState state) => default; public bool IsEnabled(LogLevel logLevel) => logLevel >= _options.LogLevel; public void Log<TState>( LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) { return; } if (formatter is null) { throw new ArgumentNullException(nameof(formatter)); } try { ClientLog log = new() { LogLevel = logLevel, EventId = eventId, Message = formatter(state, exception), Exception = exception?.Message, StackTrace = exception?.StackTrace, Url = _navigationManager.Uri }; _httpClient.PostAsJsonAsync(_options.LoggerEndpointUrl, log); } catch { // don't throw exceptions from the logger } } } }
using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Client.Logging { public class WebApiLoggerOptions { public string LoggerEndpointUrl { set; get; } public LogLevel LogLevel { get; set; } = LogLevel.Information; } }
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "WebApiLogger": { "LogLevel": "Warning", "LoggerEndpointUrl": "/api/logs" } }
namespace BlazorWasmTelegramLogger.Client { public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.Configure<WebApiLoggerOptions>(options => builder.Configuration.GetSection("WebApiLogger").Bind(options)); // … } } }
using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Shared { public class ClientLog { public LogLevel LogLevel { get; set; } public EventId EventId { get; set; } public string Message { get; set; } public string Exception { get; set; } public string StackTrace { get; set; } public string Url { get; set; } } }
namespace BlazorWasmTelegramLogger.Client { public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.Configure<WebApiLoggerOptions>(options => builder.Configuration.GetSection("WebApiLogger").Bind(options)); builder.Services.AddLogging(configure => { configure.AddWebApiLogger(); }); await builder.Build().RunAsync(); } } }
public bool IsEnabled(LogLevel logLevel) => logLevel >= _options.LogLevel;
using System; using System.Text; using System.Threading.Tasks; using BlazorWasmTelegramLogger.Shared; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Telegram.Bot; using Telegram.Bot.Types.Enums; namespace BlazorWasmTelegramLogger.Server.Services { public class TelegramLoggingBotOptions { public string AccessToken { get; set; } public string ChatId { get; set; } } public interface ITelegramBotService { Task SendLogAsync(ClientLog log); } public class TelegramBotService : ITelegramBotService { private readonly string _chatId; private readonly TelegramBotClient _client; public TelegramBotService(IOptions<TelegramLoggingBotOptions> options) { _chatId = options.Value.ChatId; _client = new TelegramBotClient(options.Value.AccessToken); } public async Task SendLogAsync(ClientLog log) { var text = formatMessage(log); if (string.IsNullOrWhiteSpace(text)) { return; } await _client.SendTextMessageAsync(_chatId, text, ParseMode.Markdown); } private static string formatMessage(ClientLog log) { if (string.IsNullOrWhiteSpace(log.Message)) { return string.Empty; } var sb = new StringBuilder(); sb.Append(toEmoji(log.LogLevel)) .Append(" *") .AppendFormat("{0:hh:mm:ss}", DateTime.Now) .Append("* ") .AppendLine(log.Message); if (!string.IsNullOrWhiteSpace(log.Exception)) { sb.AppendLine() .Append('`') .AppendLine(log.Exception) .AppendLine(log.StackTrace) .AppendLine("`") .AppendLine(); } sb.Append("*Url:* ").AppendLine(log.Url); return sb.ToString(); } private static string toEmoji(LogLevel level) => level switch { LogLevel.Trace => "⬜️", LogLevel.Debug => "🟦", LogLevel.Information => "⬛️️️", LogLevel.Warning => "🟧", LogLevel.Error => "🟥", LogLevel.Critical => "❌", LogLevel.None => "🔳", _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) }; } }
<Project Sdk="Microsoft.NET.Sdk.Web"> <ItemGroup> <PackageReference Include="Telegram.Bot" Version="15.7.1" /> </ItemGroup> </Project>
public class TelegramLoggingBotOptions { public string AccessToken { get; set; } public string ChatId { get; set; } }
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "TelegramLoggingBot": { "AccessToken": "1826…", "ChatId": "-1001…" } }
namespace BlazorWasmTelegramLogger.Server { public class Startup { // ... public void ConfigureServices(IServiceCollection services) { services.Configure<TelegramLoggingBotOptions>(options => Configuration.GetSection("TelegramLoggingBot").Bind(options)); services.AddSingleton<ITelegramBotService, TelegramBotService>(); // ... } // ... } }
public class TelegramBotService : ITelegramBotService { private readonly string _chatId; private readonly TelegramBotClient _client; public TelegramBotService(IOptions<TelegramLoggingBotOptions> options) { _chatId = options.Value.ChatId; _client = new TelegramBotClient(options.Value.AccessToken); }
using System; using System.Threading.Tasks; using BlazorWasmTelegramLogger.Server.Services; using BlazorWasmTelegramLogger.Shared; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace BlazorWasmTelegramLogger.Server.Controllers { [ApiController] [Route("api/[controller]")] public class LogsController : ControllerBase { private readonly ILogger<LogsController> _logger; private readonly ITelegramBotService _telegramBotService; public LogsController(ILogger<LogsController> logger, ITelegramBotService telegramBotService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _telegramBotService = telegramBotService; } [HttpPost] public async Task<IActionResult> PostLog(ClientLog log) { // TODO: Save the client's `log` in the database _logger.Log(log.LogLevel, log.EventId, log.Url + Environment.NewLine + log.Message); await _telegramBotService.SendLogAsync(log); return Ok(); } } }
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; throw new InvalidOperationException("This is an exception message from the client!"); } }