اس کیوال سرور
الگوهای طراحی برنامه نویسی شیءگرا
امنیت
توسعه وب
دات نت فریم ورک
دبلیو اف
سی و مشتقات
کتابهای رایگان
لینوکس
متفرقه
محیطهای مجتمع توسعه
مسایل انسانی، اجتماعی و مدیریتی برنامه نویسی
ویندوز
var customMappings = new GridifyMapper<Person>();
var customMappings = new GridifyMapper<Person>(true);
var result = _dbContext.Persons.Gridify(filter , customMappings);
customMappings.AddMap("name", q => q.FullName );
var customMappings = new GridifyMapper<Person>() .GenerateMappings() .RemoveMap("Password");
var customMappings = new GridifyMapper<Person>() .AddMap("name" , q=> q.FullName , q => q.ToLower() )
var gm = new GridifyMapper<Person>().GenerateMappings(); gm.AddMap("date", g => g.BrithDate , q => q == "null" ? null : q);
[HtmlTargetElement("img-gravatar")] public class GravatarTagHelper : TagHelper { [HtmlAttributeName("email")] public string Email { get; set; } [HtmlAttributeName("alt")] public string Alt { get; set; } [HtmlAttributeName("class")] public string Class { get; set; } [HtmlAttributeName("size")] public int Size { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { if (!string.IsNullOrWhiteSpace(Email)) { var hash = Md5HashHelper.GetHash(Email); output.TagName = "img"; if (!string.IsNullOrWhiteSpace(Class)) { output.Attributes.Add("class", Class); } if (!string.IsNullOrWhiteSpace(Alt)) { output.Attributes.Add("alt", Alt); } output.Attributes.Add("src", GetAvatarUrl(hash, Size)); output.TagMode = TagMode.SelfClosing; } } private static string GetAvatarUrl(string hash, int size) { var sizeArg = size > 0 ? $"?s={size}" : ""; return $"https://www.gravatar.com/avatar/{hash}{sizeArg}"; }
<img-gravatar email="@Model.Email" class="img-thumbnail" size="150" />
Options یا Maybe در یک زبان تابعی مثل #F، نشان دهندهی این است که شیء (Object) ممکن است وجود نداشته باشد(Null Reference) که یکی از مهمترین ویژگیهای یک زبان شیءگرا مثل #C و یا Java محسوب میشود. ما برنامه نویسها (اغلب) از هرچیزی که باعث کرش برنامه میشود، بیزاریم و برای اینکه برنامه کرش نکند، مجبور میشویم تمام کدهای خود را از Null Reference محافظت کنیم. تمام این مشکلات توسط Tony Hoare مخترع ALOGL است که تنها دلیل وجود Null References را سادگی پیاده سازی آن میداند و او این مورد را یک «خطای میلیون دلاری» نامیدهاست.
به این مثال توجه بفرمایید:
public class User { public int Id { get; set; } public string Name { get; set; } } public class UserService : IUserService { private IList<User> _userData; public UserService() { _userData = new List<User> { new User {Id = 1,Name = "ali"}, new User {Id = 2,Name = "Karim"} }; } public User GetById(int id) { return _userData.FirstOrDefault(x => x.Id == id); } } public class UserController : Controller { private readonly IUserService _userService; public UserController(IUserService userService) { _userService = userService; } public ActionResult Details(int id) { var user=_userService.GetById(3); // این متد ممکن است مقداری برگرداند و یا مقدار نال برگرداند if( user == null) return HttpNotFound(); return View(user); } }
این کدی است که ما برنامه نویسان به صورت متداولی با آن سروکار داریم. اما چه چیزی درباره این کد اشکال دارد؟
مشکل از آن جایی هست که ما نمیدانیم متد GetById مقداری را برمیگرداند و یا Null را بر میگرداند. این متد هرگاه که امکان برگرداندن Null وجود داشته باشد، خطای NullReferenceException را در زمان اجرا بر میگرداند و همان طور که میدانید، به ازای هر شرطی که به برنامه اضافه میکنیم، پیچیدگی برنامه هم افزایش مییابد و کد خوانایی خود را از دست میدهد. تصور کنید دنیایی بدون NullReferenceException چه دنیایی زیبایی میبود؛ ولی متاسفانه این مورد از ویژگیهای زبان #C است. خوشبختانه راهحلهای برای حل NRE ارائه شدهاند که در ادامه به آنها میپردازیم.
ما میخواهیم متد GetById همیشه چیزی غیر از نال را برگرداند و یکی از راههایی که ما را به این هدف میرساند این است که این متد یک توالی را برگرداند.
public class UserService : IUserService { private IList<User> _userData; public UserService() { _userData = new List<User> { new User {Id = 1,Name = "ali"}, new User {Id = 2,Name = "Karim"} }; } public IEnumerable<User> GetById(int id) { var user = _userData.FirstOrDefault(x => x.Id == id); if (user == null) return new User[0]; return new[] { user }; } }
اگر به امضای متد GetById توجه کنید، به جای اینکه User را برگرداند، این متد یک توالی از User را بر میگرداند و اگر در اینجا کاربری یافت شد، این توالی دارای یک المان خواهد بود و در غیر این صورت اگر User یافت نشد، این متد یک توالی را بر میگرداند که دارای هیچ المانی نیست. در ادامه اگر کلاینت بخواهد از متد GetById استفاده کند، به صورت زیر خواهد بود:
public ActionResult Details(int id) { var user = _userService .GetById(3) .DefaultIfEmpty(new User()) .Single(); return View(user); }
متد GetById دارای دو وجه است و وجه مثبت آن این است که اگر مجموعه دارای مقداری باشد، هیچ مشکلی نیست؛ ولی اگر مجموعه دارای المانی نباشد، باید یک شیء را به صورت پیش فرض به آن اختصاص دهیم که این کار را با استفاده از متد DefualtIfEmpty انجام دادهایم.
در اول مقاله هم اشاره کردیم که Maybe یا Options، مجموعهای است که دارای یک المان و یا هیچ المانی است. اگر به امضای متد GetById توجه کنید، متوجه خواهید شد که این متد میتواند مجموعهای را برگرداند و نمیتواند گارانتی کند که حتما مجموعهای را بر میگرداند که دارای یک المان و یا هیچ باشد. برای حل این مشکل میتوانیم از کلاس Option استفاده کنیم:
public class Option<T> : IEnumerable<T> { private readonly T[] _data; private Option(T[] data) { _data = data; } public static Option<T> Create(T element) => new Option<T>(new[] { element }); public static Option<T> CreateEmpty() => new Option<T>(new T[0]); public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>) _data).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); }
تنها دلیل استفاده از متدهای Create و CreateEmpty این است که به خوانایی برنامه کمک کنیم؛ نه بیشتر. در ادامه اگر بخواهیم از کلاس option استفاده کنیم، به صورت زیر خواهد بود:
public class UserService : IUserService { ... ... public Option<User> GetById(int id) { var user = _userData.FirstOrDefault(x => x.Id == id); return user == null ? Option<User>.CreateEmpty() : Option<User>.Create(user); } } public class UserController : Controller { ... ... public ActionResult Details(int id) { var user = _userService .GetById(3) .DefaultIfEmpty(new User()) .Single(); return View(user); } }
چکیده:
مدیریت کردن References کار بسیار پیچیدهای است. قبل از آن که تلاش کنیم مقداری را برگردانیم و یا عملیاتی را بر روی آن انجام دهیم، اول باید مطمئن شویم که این شیء به جایی اشاره میکند. نمونههای متفاوتی از Option و یا Maybe را میتوانید در اینترنت پیدا کنید که هدف نهایی آنها، حذف NullReferenceException است و آشنایی با این ایده، شما را به دنیای برنامه نویسی تابعی در#C هدایت میکند.
namespace CS11Tests; public class StaticAbstractMembers { public static void Test() { var sum = AddAll(new[] { 1, 2, 3, 4 }); Console.WriteLine(sum); } private static int AddAll(int[] values) { int result = 0; foreach (var value in values) { result += value; } return result; } }
var sum = AddAll(new[] { 1, 2, 3, 4, 0.68 });
Argument 1: cannot convert from 'double[]' to 'int[]' [CS11Tests]csharp(CS1503)
private static T AddAll<T>(T[] values) { T result = 0; foreach (var value in values) { result += value; } return result; }
T result = T.Zero;
using System.Numerics; namespace CS11Tests; public class StaticAbstractMembers { public static void Test() { //var sum = AddAll(new[] { 1, 2, 3, 4 }); var sum = AddAll(new[] { 1, 2, 3, 4, 0.68 }); Console.WriteLine(sum); } private static T AddAll<T>(T[] values) where T : INumber<T> { T result = T.Zero; foreach (var value in values) { result += value; } return result; } }
abstract static TSelf One { get; } abstract static TSelf Zero { get; }
abstract static TResult operator +(TSelf left, TOther right);
public interface ISport { bool IsTeamSport(); } public class Swimming : ISport { public bool IsTeamSport() => false; } public class Football : ISport { public bool IsTeamSport() => true; }
public class StaticAbstractMembers { public static void Display<T>(T sport) where T : ISport { Console.WriteLine("Is Team Sport:" + sport.IsTeamSport()); } }
Display(new Football());
public interface ISport { static abstract bool IsTeamSport(); } public class Swimming : ISport { public static bool IsTeamSport() => false; } public class Football : ISport { public static bool IsTeamSport() => true; }
public class StaticAbstractMembers { public static void Display<T>() where T : ISport { Console.WriteLine("Is Team Sport:" + T.IsTeamSport()); } }
namespace NHSample2.Domain
{
public class User
{
public virtual int Id { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
}
}
namespace NHSample2.Domain
{
public class Category
{
public virtual int Id { get; set; }
public virtual string CategoryName { get; set; }
}
}
using System;
namespace NHSample2.Domain
{
public class News
{
public virtual Guid Id { get; set; }
public virtual string Subject { get; set; }
public virtual string NewsText { get; set; }
public virtual DateTime DateEntered { get; set; }
public virtual Category Category { get; set; }
public virtual User User { get; set; }
}
}
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace NHSample2
{
class Config
{
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Where(x => x.Namespace.EndsWith("Domain"))
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly).Configure(cfg);
return cfg;
}
public static void GenerateDbScript(Configuration config, string filePath)
{
bool script = true;//فقط اسکریپت دیتابیس تولید گردد
bool export = false;//نیازی نیست بر روی دیتابیس هم اجرا شود
new SchemaExport(config).SetOutputFile(filePath).Create(script, export);
}
public static void BuildDbSchema(Configuration config)
{
bool script = false;//آیا خروجی در کنسول هم نمایش داده شود
bool export = true;//آیا بر روی دیتابیس هم اجرا شود
bool drop = false;//آیا اطلاعات موجود دراپ شوند
new SchemaExport(config).Execute(script, export, drop);
}
public static void CreateSQL2008DbPlusScript(string connectionString, string filePath)
{
Configuration cfg =
GenerateMapping(
MsSqlConfiguration
.MsSql2008
.ConnectionString(connectionString)
.ShowSql()
);
GenerateDbScript(cfg, filePath);
BuildDbSchema(cfg);
}
public static ISessionFactory CreateSessionFactory(IPersistenceConfigurer dbType)
{
return
Fluently.Configure().Database(dbType)
.Mappings(m => m.AutoMappings
.Add(
new AutoPersistenceModel()
.Where(x => x.Namespace.EndsWith("Domain"))
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly))
)
.BuildSessionFactory();
}
}
}
using System;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
Config.CreateSQL2008DbPlusScript(
"Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true",
"db.sql");
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
create table [Category] (
Id INT IDENTITY NOT NULL,
CategoryName NVARCHAR(255) null,
primary key (Id)
)
create table [User] (
Id INT IDENTITY NOT NULL,
UserName NVARCHAR(255) null,
Password NVARCHAR(255) null,
primary key (Id)
)
create table [News] (
Id UNIQUEIDENTIFIER not null,
Subject NVARCHAR(255) null,
NewsText NVARCHAR(255) null,
DateEntered DATETIME null,
Category_id INT null,
User_id INT null,
primary key (Id)
)
alter table [News]
add constraint FKE660F9E1C9CF79
foreign key (Category_id)
references [Category]
alter table [News]
add constraint FKE660F95C1A3C92
foreign key (User_id)
references [User]
using System;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHSample2.Domain;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
using (ISessionFactory sessionFactory = Config.CreateSessionFactory(
MsSqlConfiguration
.MsSql2008
.ConnectionString("Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true")
.ShowSql()
))
{
using (ISession session = sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//با توجه به کلیدهای خارجی تعریف شده ابتدا باید گروهها را اضافه کرد
Category ca = new Category() { CategoryName = "Sport" };
session.Save(ca);
Category ca2 = new Category() { CategoryName = "IT" };
session.Save(ca2);
Category ca3 = new Category() { CategoryName = "Business" };
session.Save(ca3);
//سپس یک کاربر را به دیتابیس اضافه میکنیم
User u = new User() { Password = "123$5@1", UserName = "VahidNasiri" };
session.Save(u);
//اکنون میتوان یک خبر جدید را ثبت کرد
News news = new News()
{
Category = ca,
User = u,
DateEntered = DateTime.Now,
Id = Guid.NewGuid(),
NewsText = "متن خبر جدید",
Subject = "عنوانی دلخواه"
};
session.Save(news);
transaction.Commit(); //پایان تراکنش
}
}
}
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
using System.Linq;
using NHibernate;
using NHibernate.Linq;
using NHSample2.Domain;
namespace NHSample2
{
class NewsContext : NHibernateContext
{
public NewsContext(ISession session)
: base(session)
{ }
public IOrderedQueryable<News> News
{
get { return Session.Linq<News>(); }
}
public IOrderedQueryable<Category> Categories
{
get { return Session.Linq<Category>(); }
}
public IOrderedQueryable<User> Users
{
get { return Session.Linq<User>(); }
}
}
}
using System;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using System.Linq;
using NHSample2.Domain;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
using (ISessionFactory sessionFactory = Config.CreateSessionFactory(
MsSqlConfiguration
.MsSql2008
.ConnectionString("Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true")
.ShowSql()
))
{
using (ISession session = sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
using (NewsContext db = new NewsContext(session))
{
var query = from x in db.Users
where x.UserName == "VahidNasiri"
select x;
//اگر چیزی یافت شد
if (query.Any())
{
User vahid = query.First();
//نمایش اطلاعات کاربر
Console.WriteLine("Id: {0}, UserName: {0}", vahid.Id, vahid.UserName);
//به روز رسانی نام کاربر
vahid.UserName = "Vahid";
session.Update(vahid);
transaction.Commit(); //پایان تراکنش
}
}
}
}
}
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
using FluentNHibernate.Conventions.Helpers;
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Conventions.Add()
.Where(x => x.Namespace.EndsWith("Domain"))
.Conventions.Add(
PrimaryKey.Name.Is(x => "ID"),
DefaultLazy.Always(),
ForeignKey.EndsWith("ID"),
Table.Is(t => "tbl" + t.EntityType.Name)
)
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly)
.Configure(cfg);
return cfg;
}
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
namespace NHSample2.Conventions
{
class MyStringLengthConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
instance.Length(500);
}
}
}
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Conventions.Add()
.Where(x => x.Namespace.EndsWith("Domain"))
.Conventions.Add<MyStringLengthConvention>()
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly)
.Configure(cfg);
return cfg;
}
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Mvc; namespace SecurityModule { public class AllowUploadSpecialFilesOnlyAttribute : ActionFilterAttribute { readonly List<string> _toFilter = new List<string>(); readonly string _extensionsWhiteList; public AllowUploadSpecialFilesOnlyAttribute(string extensionsWhiteList) { if (string.IsNullOrWhiteSpace(extensionsWhiteList)) throw new ArgumentNullException("extensionsWhiteList"); _extensionsWhiteList = extensionsWhiteList; var extensions = extensionsWhiteList.Split(','); foreach (var ext in extensions.Where(ext => !string.IsNullOrWhiteSpace(ext))) { _toFilter.Add(ext.ToLowerInvariant().Trim()); } } bool canUpload(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) return false; var ext = Path.GetExtension(fileName.ToLowerInvariant()); return _toFilter.Contains(ext); } public override void OnActionExecuting(ActionExecutingContext filterContext) { var files = filterContext.HttpContext.Request.Files; foreach (string file in files) { var postedFile = files[file]; if (postedFile == null || postedFile.ContentLength == 0) continue; if (!canUpload(postedFile.FileName)) throw new InvalidOperationException( string.Format("You are not allowed to upload {0} file. Please upload only these files: {1}.", Path.GetFileName(postedFile.FileName), _extensionsWhiteList)); } base.OnActionExecuting(filterContext); } } }
[AllowUploadSpecialFilesOnly(".jpg,.gif,.png")] public ActionResult ImageUpload(HttpPostedFileBase file)
public static bool IsImageFile(HttpPostedFileBase photoFile) { using (var img = Image.FromStream(photoFile.InputStream)) { return img.Width > 0; } }
Unable to update database to match the current model because there are pending changes and
automatic migration is disabled. Either write the pending model changes to a code-based migration
or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true
to enable automatic migration.
Add-Migration AddSomeProp2ToProject
namespace EF_Sample02.Migrations
{
using System.Data.Entity.Migrations;
public partial class AddSomeProp2ToProject : DbMigration
{
public override void Up()
{
AddColumn("Projects", "SomeProp", c => c.String());
AddColumn("Projects", "SomeProp2", c => c.String());
}
public override void Down()
{
DropColumn("Projects", "SomeProp2");
DropColumn("Projects", "SomeProp");
}
}
}
Update-Database -Verbose
Using NuGet project 'EF_Sample02'.
Using StartUp project 'EF_Sample02'.
Target database is: 'testdb2012' (DataSource: (local), Provider: System.Data.SqlClient, Origin: Configuration).
Applying explicit migrations: [201205061835024_AddSomeProp2ToProject].
Applying explicit migration: 201205061835024_AddSomeProp2ToProject.
ALTER TABLE [Projects] ADD [SomeProp] [nvarchar](max)
ALTER TABLE [Projects] ADD [SomeProp2] [nvarchar](max)
[Inserting migration history record]
Add-Migration AddSomeProp3ToProject
Update-Database -Verbose
get-help update-database -detailed
Update-Database -TargetMigration:"AddSomeProp2ToProject" -Verbose
Using NuGet project 'EF_Sample02'.
Using StartUp project 'EF_Sample02'.
Target database is: 'testdb2012' (DataSource: (local), Provider: System.Data.SqlClient, Origin: Configuration).
Reverting migrations: [201205061845485_AddSomeProp3ToProject].
Reverting explicit migration: 201205061845485_AddSomeProp3ToProject.
DECLARE @var0 nvarchar(128)
SELECT @var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'Projects')
AND col_name(parent_object_id, parent_column_id) = 'SomeProp3';
IF @var0 IS NOT NULL
EXECUTE('ALTER TABLE [Projects] DROP CONSTRAINT ' + @var0)
ALTER TABLE [Projects] DROP COLUMN [SomeProp3]
[Deleting migration history record]
namespace EF_Sample02.Migrations
{
using System.Data.Entity.Migrations;
public partial class AddSomeProp3ToProject : DbMigration
{
public override void Up()
{
AddColumn("Projects", "SomeProp3", c => c.String(defaultValue: "some data"));
Sql("Update Projects set SomeProp3=N'some data'");
}
public override void Down()
{
DropColumn("Projects", "SomeProp3");
}
}
}
public ColumnModel String(bool? nullable = null, int? maxLength = null, bool? fixedLength = null,
bool? isMaxLength = null, bool? unicode = null, string defaultValue = null, string defaultValueSql = null,
string name = null, string storeType = null)
ALTER TABLE [Projects] ADD [SomeProp3] [nvarchar](max) DEFAULT 'some data'
namespace EF_Sample02.Migrations
{
using System;
using System.Data.Entity.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<EF_Sample02.Sample2Context>
{
public Configuration()
{
this.AutomaticMigrationsEnabled = false;
this.AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(EF_Sample02.Sample2Context context)
{
context.Users.AddOrUpdate(
a => a.Name,
new Models.User { Name = "Vahid", AddDate = DateTime.Now },
new Models.User { Name = "Test", AddDate = DateTime.Now });
}
}
}
Update-Database -Verbose -Script
ALTER TABLE [Projects] ADD [SomeProp5] [nvarchar](max)
INSERT INTO [__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES
('201205060852004_AutomaticMigration', '2012-05-06T08:52:00.937Z', 0x1F8B0800000............ '4.3.1')
Update-Database -Verbose -Script -SourceMigration:"stepName"
Add-Migration AddSomePropToProject
Update-Database -Verbose -Script