public class ProductsRequest { // نام این خاصیت نباید تغییر یابد public IEnumerable<Product> Models { get; set; } }
public HttpResponseMessage Update(ProductsRequest products) {
public class ProductsRequest { // نام این خاصیت نباید تغییر یابد public IEnumerable<Product> Models { get; set; } }
public HttpResponseMessage Update(ProductsRequest products) {
سناریویی را در نظر بگیرید که در آن عملیات CRUD توسط WCF پیاده سازی شده اند و دسترسی دادهها با مدل Code-First انجام میشود. فرض کنید مدل اپلیکیشن مانند تصویر زیر است.
همانطور که میبینید مدل ما متشکل از پستها و نظرات کاربران است. برای ساده نگاه داشتن مثال جاری، اکثر فیلدها حذف شده اند. مثلا متن پست ها، نویسنده، تاریخ و زمان انتشار و غیره. میخواهیم تمام کد دسترسی دادهها را در یک سرویس WCF پیاده سازی کنیم تا کلاینتها بتوانند عملیات CRUD را توسط آن انجام دهند. برای ساختن این سرویس مراحل زیر را دنبال کنید.
[DataContract(IsReference = true)] public class Post { public Post() { comments = new HashSet<Comments>(); } [DataMember] public int PostId { get; set; } [DataMember] public string Title { get; set; } [DataMember] public virtual ICollection<Comment> Comments { get; set; } } [DataContract(IsReference=true)] public class Comment { [DataMember] public int CommentId { get; set; } [DataMember] public int PostId { get; set; } [DataMember] public string CommentText { get; set; } [DataMember] public virtual Post Post { get; set; } } public class EFRecipesEntities : DbContext { public EFRecipesEntities() : base("name=EFRecipesEntities") {} public DbSet<Post> posts; public DbSet<Comment> comments; }
<connectionStrings> <add name="Recipe2ConnectionString" connectionString="Data Source=.; Initial Catalog=EFRecipes; Integrated Security=True; MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> </connectionStrings>
[ServiceContract] public interface IService1 { [OperationContract] void Cleanup(); [OperationContract] Post GetPostByTitle(string title); [OperationContract] Post SubmitPost(Post post); [OperationContract] Comment SubmitComment(Comment comment); [OperationContract] void DeleteComment(Comment comment); }
public class Service1 : IService { public void Cleanup() { using (var context = new EFRecipesEntities()) { context.Database.ExecuteSqlCommand("delete from [comments]"); context. Database.ExecuteSqlCommand ("delete from [posts]"); } } public Post GetPostByTitle(string title) { using (var context = new EFRecipesEntities()) { context.Configuration.ProxyCreationEnabled = false; var post = context.Posts.Include(p => p.Comments).Single(p => p.Title == title); return post; } } public Post SubmitPost(Post post) { context.Entry(post).State = // if Id equal to 0, must be insert; otherwise, it's an update post.PostId == 0 ? EntityState.Added : EntityState.Modified; context.SaveChanges(); return post; } public Comment SubmitComment(Comment comment) { using (var context = new EFRecipesEntities()) { context.Comments.Attach(comment); if (comment.CommentId == 0) { // this is an insert context.Entry(comment).State = EntityState.Added); } else { // set single property to modified, which sets state of entity to modified, but // only updates the single property – not the entire entity context.entry(comment).Property(x => x.CommentText).IsModified = true; } context.SaveChanges(); return comment; } } public void DeleteComment(Comment comment) { using (var context = new EFRecipesEntities()) { context.Entry(comment).State = EntityState.Deleted; context.SaveChanges(); } } }
class Program { static void Main(string[] args) { using (var client = new ServiceReference2.Service1Client()) { // cleanup previous data client.Cleanup(); // insert a post var post = new Post { Title = "POCO Proxies" }; post = client.SubmitPost(post); // update the post post.Title = "Change Tracking Proxies"; client.SubmitPost(post); // add a comment var comment1 = new Comment { CommentText = "Virtual Properties are cool!", PostId = post.PostId }; var comment2 = new Comment { CommentText = "I use ICollection<T> all the time", PostId = post.PostId }; comment1 = client.SubmitComment(comment1); comment2 = client.SubmitComment(comment2); // update a comment comment1.CommentText = "How do I use ICollection<T>?"; client.SubmitComment(comment1); // delete comment 1 client.DeleteComment(comment1); // get posts with comments var p = client.GetPostByTitle("Change Tracking Proxies"); Console.WriteLine("Comments for post: {0}", p.Title); foreach (var comment in p.Comments) { Console.WriteLine("\tComment: {0}", comment.CommentText); } } } }
ابتدا با اپلیکیشن کنسول شروع میکنیم، که کلاینت سرویس ما است. نخست در یک بلاک {} using وهله ای از کلاینت سرویس مان ایجاد میکنیم. درست همانطور که وهله ای از یک EF Context میسازیم. استفاده از بلوکهای using توصیه میشود چرا که متد Dispose بصورت خودکار فراخوانی خواهد شد، چه بصورت عادی چه هنگام بروز خطا. پس از آنکه وهله ای از کلاینت سرویس را در اختیار داشتیم، متد Cleanup را صدا میزنیم. با فراخوانی این متد تمام دادههای تست پیشین را حذف میکنیم. در چند خط بعدی، متد SubmitPost را روی سرویس فراخوانی میکنیم. در پیاده سازی فعلی شناسه پست را بررسی میکنیم. اگر مقدار شناسه صفر باشد، خاصیت State موجودیت را به Added تغییر میدهید تا رکورد جدیدی ثبت کنیم. در غیر اینصورت فرض بر این است که چنین موجودیتی وجود دارد و قصد ویرایش آن را داریم، بنابراین خاصیت State را به Modified تغییر میدهیم. از آنجا که مقدار متغیرهای int بصورت پیش فرض صفر است، با این روش میتوانیم وضعیت پستها را مشخص کنیم. یعنی تعیین کنیم رکورد جدیدی باید ثبت شود یا رکوردی موجود بروز رسانی گردد. رویکردی بهتر آن است که پارامتری اضافی به متد پاس دهیم، یا متدی مجزا برای ثبت رکوردهای جدید تعریف کنیم. مثلا رکوردی با نام InsertPost. در هر حال، بهترین روش بستگی به ساختار اپلیکیشن شما دارد.
اگر پست جدیدی ثبت شود، خاصیت PostId با مقدار مناسب جدید بروز رسانی میشود و وهله پست را باز میگردانیم. ایجاد و بروز رسانی نظرات کاربران مشابه ایجاد و بروز رسانی پستها است، اما با یک تفاوت اساسی: بعنوان یک قانون، هنگام بروز رسانی نظرات کاربران تنها فیلد متن نظر باید بروز رسانی شود. بنابراین با فیلدهای دیگری مانند تاریخ انتشار و غیره اصلا کاری نخواهیم داشت. بدین منظور تنها خاصیت CommentText را بعنوان Modified علامت گذاری میکنیم. این امر منجر میشود که Entity Framework عبارتی برای بروز رسانی تولید کند که تنها این فیلد را در بر میگیرد. توجه داشته باشید که این روش تنها در صورتی کار میکند که بخواهید یک فیلد واحد را بروز رسانی کنید. اگر میخواستیم فیلدهای بیشتری را در موجودیت Comment بروز رسانی کنیم، باید مکانیزمی برای ردیابی تغییرات در سمت کلاینت در نظر میگرفتیم. در مواقعی که خاصیتهای متعددی میتوانند تغییر کنند، معمولا بهتر است کل موجودیت بروز رسانی شود تا اینکه مکانیزمی پیچیده برای ردیابی تغییرات در سمت کلاینت پیاده گردد. بروز رسانی کل موجودیت بهینهتر خواهد بود.
برای حذف یک دیدگاه، متد Entry را روی آبجکت DbContext فراخوانی میکنیم و موجودیت مورد نظر را بعنوان آرگومان پاس میدهیم. این امر سبب میشود که موجودیت مورد نظر بعنوان Deleted علامت گذاری شود، که هنگام فراخوانی متد SaveChanges اسکریپت لازم برای حذف رکورد را تولید خواهد کرد.
در آخر متد GetPostByTitle یک پست را بر اساس عنوان پیدا کرده و تمام نظرات کاربران مربوط به آن را هم بارگذاری میکند. از آنجا که ما کلاسهای POCO را پیاده سازی کرده ایم، Entity Framework آبجکتی را بر میگرداند که Dynamic Proxy نامیده میشود. این آبجکت پست و نظرات مربوط به آن را در بر خواهد گرفت. متاسفانه WCF نمیتواند آبجکتهای پروکسی را مرتب سازی (serialize) کند. اما با غیرفعال کردن قابلیت ایجاد پروکسیها (ProxyCreationEnabled=false) ما به Entity Framework میگوییم که خود آبجکتهای اصلی را بازگرداند. اگر سعی کنید آبجکت پروکسی را سریال کنید با پیغام خطای زیر مواجه خواهید شد:
The underlying connection was closed: The connection was closed unexpectedly
می توانیم غیرفعال کردن تولید پروکسی را به متد سازنده کلاس سرویس منتقل کنیم تا روی تمام متدهای سرویس اعمال شود.
در این قسمت دیدیم چگونه میتوانیم از آبجکتهای POCO برای مدیریت عملیات CRUD توسط WCF استفاده کنیم. از آنجا که هیچ اطلاعاتی درباره وضعیت موجودیتها روی کلاینت ذخیره نمیشود، متدهایی مجزا برای عملیات CRUD ساختیم. در قسمتهای بعدی خواهیم دید چگونه میتوان تعداد متدهایی که سرویس مان باید پیاده سازی کند را کاهش داد و چگونه ارتباطات بین کلاینت و سرور را سادهتر کنیم.
One or more validation errors were detected during model generation:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'Blog' has no key defined.
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EF_Sample01.Models
{
public class Blog
{
[Key]
public int MyTableKey { set; get; }
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EF_Sample01.Models
{
public class Blog
{
[Key]
public int MyTableKey { set; get; }
[MaxLength(100)]
public string Title { set; get; }
[Required]
public string AuthorName { set; get; }
public IList<Post> Posts { set; get; }
}
}
CREATE TABLE [dbo].[Blogs](
[MyTableKey] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](100) NULL,
[AuthorName] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Blogs] PRIMARY KEY CLUSTERED
(
[MyTableKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
[Required(ErrorMessage = "لطفا نام نویسنده را مشخص نمائید")]
public string AuthorName { set; get; }
using System.Data.Entity;
using EF_Sample01.Models;
namespace EF_Sample01
{
public class Context : DbContext
{
public DbSet<Blog> Blogs { set; get; }
public DbSet<Post> Posts { set; get; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().HasKey(x => x.MyTableKey);
modelBuilder.Entity<Blog>().Property(x => x.Title).HasMaxLength(100);
modelBuilder.Entity<Blog>().Property(x => x.AuthorName).IsRequired();
base.OnModelCreating(modelBuilder);
}
}
}
using System.Data.Entity;
using EF_Sample01.Models;
using System.Data.Entity.ModelConfiguration;
namespace EF_Sample01
{
public class BlogConfig : EntityTypeConfiguration<Blog>
{
public BlogConfig()
{
this.Property(x => x.Id).HasColumnName("MyTableKey");
this.Property(x => x.RowVersion).HasColumnType("Timestamp");
}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new BlogConfig());
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EF_Sample01.Models
{
[Table("tblBlogs")]
public class Blog
{
[Column("MyTableKey")]
public int Id { set; get; }
[MaxLength(100)]
public string Title { set; get; }
[Required(ErrorMessage = "لطفا نام نویسنده را مشخص نمائید")]
public string AuthorName { set; get; }
public IList<Post> Posts { set; get; }
[Timestamp]
public byte[] RowVersion { set; get; }
}
}
modelBuilder.Entity<Blog>().ToTable("tblBlogs");
modelBuilder.Entity<Blog>().Property(x => x.Id).HasColumnName("MyTableKey");
modelBuilder.Entity<Blog>().Property(x => x.RowVersion).HasColumnType("Timestamp");
System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
// or
System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
public class MyInitializer : IDatabaseInitializer<Context>
{
public void InitializeDatabase(Context context)
{
if (context.Database.Exists() ||
context.Database.CompatibleWithModel(throwIfNoMetadata: false))
context.Database.Delete();
context.Database.Create();
}
}
System.Data.Entity.Database.SetInitializer(new MyInitializer());
Database.SetInitializer<Context>(null);
<appSettings>
<add key="DatabaseInitializerForType MyNamespace.MyDbContextClass, MyAssembly"
value="MyNamespace.MyInitializerClass, MyAssembly" />
</appSettings>
<appSettings>
<add key="DatabaseInitializerForType MyNamespace.MyDbContextClass, MyAssembly"
value="Disabled" />
</appSettings>
<appSettings>
<add key="DatabaseInitializerForType EF_Sample01.Context, EF_Sample01"
value="EF_Sample01.MyInitializer, EF_Sample01" />
</appSettings>
public class MyCustomInitializer : DropCreateDatabaseIfModelChanges<Context>
{
protected override void Seed(Context context)
{
context.Blogs.Add(new Blog { AuthorName = "Vahid", Title = ".NET Tips" });
context.Database.ExecuteSqlCommand("CREATE INDEX IX_title ON tblBlogs (title)");
base.Seed(context);
}
}
Server=(local);Database=yourDatabase;User ID=yourDBUser;Password=yourDBPassword;Trusted_Connection=False;Persist Security Info=True
[Table("tblBlogs", Schema="someUser")]
public class Blog
modelBuilder.Entity<Blog>().ToTable("tblBlogs", schemaName:"someUser");
Install-Package mongocsharpdriver
public class Author { public ObjectId Id { get; set; } public string Name { get; set; } }
public class Language { public ObjectId Id { get; set; } public string Name { get; set; } }
public class Book { public ObjectId Id { get; set; } public string Title { get; set; } public string ISBN { get; set; } public int Price { get; set; } public List<Author> Authors { get; set; } public Language Language { get; set; } }
var book =new Book() { Title = "Gone With Wind", ISBN = "43442424", Price = 50000, Language = new Language() { Name = "Persian" }, Authors = new List<Author>() { new Author() { Name = "Margaret Mitchell" }, new Author() { Name = "Ali Mahboobi (Translator)" }, } };
var client = new MongoClient();
string connectionString = "mongodb://localhost:27017"; MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString)); var client = new MongoClient(settings);
var db = client.GetDatabase("publisher");
var collection = db.GetCollection<Book>("books");
collection.InsertOneAsync(book);
فعلا موجودیتهای مؤلفان و زبان به دلیل اینکه سند اختصاصی برای خود ندارند، با صفر پر شدهاند؛ ولی شناسه یکتای سند، مقدار خود را گرفته است.
عملیات خواندن
var client = new MongoClient(); var db = client.GetDatabase("publisher"); db.DropCollection("books"); var collection = db.GetCollection<Book>("books"); var book =new Book() { Title = "Gone With Wind", ISBN = "43442424", Price = 50000, Year = 1936, LastStock = DateTime.Now.AddDays(-13), Language = new Language() { Name = "Persian" }, Authors = new List<Author>() { new Author() { Name = "Margaret Mitchell" }, new Author() { Name = "Ali Mahboobi (Translator)" }, } }; var book2 = new Book() { Title = "Jane Eyre", ISBN = "87897897", Price = 60000, Year = 1847, LastStock = DateTime.Now.AddDays(-5), Language = new Language() { Name = "English" }, Authors = new List<Author>() { new Author() { Name = "Charlotte Brontë" }, } }; var book3 = new Book() { Title = "White Fang", ISBN = "43442424", Price = 50000, Year = 1936, LastStock = DateTime.Now.AddDays(-13), Language = new Language() { Name = "English" }, Authors = new List<Author>() { new Author() { Name = "Jack London" }, new Author() { Name = "Philippe Mignon" }, } }; var book4 = new Book() { Title = "The Lost Symbol", ISBN = "43442424", Price = 3500000, Year = 2009, LastStock = DateTime.Now.AddDays(-17), Language = new Language() { Name = "Persian" }, Authors = new List<Author>() { new Author() { Name = "Dan Brown" }, new Author() { Name = "Mehrdad" }, } }; var book7 = new Book() { Title = "The Lost Symbol", ISBN = "43442424", Price = 47000000, Year = 2009, LastStock = DateTime.Now.AddDays(-56), Language = new Language() { Name = "Persian" }, Authors = new List<Author>() { new Author() { Name = "Dan Brown" }, new Author() { Name = "Mehrdad" }, } }; var book5= new Book() { Title = "The Help", ISBN = "45345e3er3", Price = 9000000, Year = 2009, LastStock = DateTime.Now.AddDays(-2), Language = new Language() { Name = "Enlish" }, Authors = new List<Author>() { new Author() { Name = "Kathryn Stockett" }, } }; var book6 = new Book() { Title = "City of Glass", ISBN = "454534545", Price = 500000, Year = 2009, LastStock = DateTime.Now, Language = new Language() { Name = "Persian" }, Authors = new List<Author>() { new Author() { Name = "Cassandra Clare" }, new Author() { Name = "Ali" }, } }; var books = new List<Book> {book, book2, book3, book4, book5, book6,book7}; collection.InsertManyAsync(books);
var client = new MongoClient(); var db = client.GetDatabase("publisher"); var collection = db.GetCollection<Book>("books"); var filter=new BsonDocument(); var docs = collection.Find(filter).ToList(); foreach (var book in docs) { Console.WriteLine(book.Title + " By "+ book.Authors[0].Name); }
Gone With Wind By Margaret Mitchell Jane Eyre By Charlotte Brontë White Fang By Jack London The Lost Symbol By Dan Brown The Help By Kathryn Stockett City of Glass By Cassandra Clare The Lost Symbol By Dan Brown
var filter = Builders<Book>.Filter.Eq("Year", 2009); var docs = collection.Find(filter).ToList(); foreach (var book in docs) { Console.WriteLine(book.Title + " By "+ book.Authors[0].Name); }
The Lost Symbol By Dan Brown The Help By Kathryn Stockett City of Glass By Cassandra Clare The Lost Symbol By Dan Brown
// var filter=new BsonDocument(); var filterBuilder = Builders<Book>.Filter; var filter= filterBuilder.Eq("Year", 2009) | filterBuilder.Gte("Price",700000); var docs = collection.Find(filter).ToList(); foreach (var book in docs) { Console.WriteLine(book.Title + " By "+ book.Authors[0].Name); }
Gone With Wind By Margaret Mitchell White Fang By Jack London The Lost Symbol By Dan Brown The Help By Kathryn Stockett City of Glass By Cassandra Clare The Lost Symbol By Dan Brown
var docs = collection.AsQueryable().Where(x => x.Year == 2009 || x.Price <= 50000).ToList();
var sort = Builders<Book>.Sort.Ascending("Title").Descending("Price"); var docs = collection.Find(filter).Sort(sort).ToList(); foreach (var book in docs) { Console.WriteLine(book.Title + " By "+ book.Authors[0].Name); }
City of Glass By Cassandra Clare Gone With Wind By Margaret Mitchell The Help By Kathryn Stockett The Lost Symbol By Dan Brown The Lost Symbol By Dan Brown White Fang By Jack London
var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
using Newtonsoft.Json; namespace JsonNetTests { public enum Color { Red, Green, Blue, White } public class Item { public string Name { set; get; } public Color Color { set; get; } } public class EnumTests { public string GetJson() { var item = new Item { Name = "Item 1", Color = Color.Blue }; return JsonConvert.SerializeObject(item, Formatting.Indented); } } }
{ "Name": "Item 1", "Color": 2 }
[JsonConverter(typeof(StringEnumConverter))] public Color Color { set; get; }
return JsonConvert.SerializeObject(item, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = { new StringEnumConverter() } });
public class Category { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Product> Products { get; set; } public Category() { Products = new List<Product>(); } } public class Product { public int Id { get; set; } public string Name { get; set; } public virtual Category Category { get; set; } }
using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace JsonNetTests { public class SelfReferencingLoops { public string GetJson() { var category = new Category { Id = 1, Name = "Category 1" }; var product = new Product { Id = 1, Name = "Product 1" }; category.Products.Add(product); product.Category = category; return JsonConvert.SerializeObject(category, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = { new StringEnumConverter() } }); } } }
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll Additional information: Self referencing loop detected for property 'Category' with type 'JsonNetTests.Category'. Path 'Products[0]'.
return JsonConvert.SerializeObject(category, new JsonSerializerSettings { Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, Converters = { new StringEnumConverter() } });
return JsonConvert.SerializeObject(category, new JsonSerializerSettings { Formatting = Formatting.Indented, PreserveReferencesHandling = PreserveReferencesHandling.Objects, Converters = { new StringEnumConverter() } });
{ "$id": "1", "Id": 1, "Name": "Category 1", "Products": [ { "$id": "2", "Id": 1, "Name": "Product 1", "Category": { "$ref": "1" } } ] }
A library that provides a simple way to create lambda expressions to filter lists and database queries.
var filter = new Filter<Person>(); filter.By("Id", Operation.Between, 2, 4, Connector.And); filter.By("Contacts[Value]", Operation.EndsWith, "@email.com", default(string), Connector.And); filter.By("Birth.Country", Operation.IsNotNull, default(string), default(string), Connector.Or); filter.By("Name", Operation.Contains, " John"); var people = People.Where(filter); //or like this... var filter = new Filter<Person>(); filter.By("Id", Operation.Between, 2, 4) .And.By("Birth.Country", Operation.IsNotNull) .And.By("Contacts[Value]", Operation.EndsWith, "@email.com") .Or.By("Name", Operation.Contains, " John "); var people = People.Where(filter);
So that would generate an expression like this:
People.Where(p => (p.Id >= 2 && p.Id <= 4) && (p.Birth != null && p.Birth.Country != null) && (p.Contacts != null && p.Contacts.Any(c => c.Value.Trim().ToLower().EndsWith("@email.com"))) || (p.Name != null && p.Name.Trim().ToLower().Contains("john")));
["Adventure Works","Contoso"]
a) AjaxHelper
b) XDocument
c) JsonResult
d) DataContractJsonSerializer
a) Use the Html.RenderPartial extension method
b) Use the Html.RenderAction extension method
c) Use the PartialViewResult class
d) Use the ContentResult class
public class Player
{
public String Name { get; set; }
public int LastScore { get; set; }
public int HighScore { get; set; }
}
[UIHint("Score")]
[Display(Name="LastScore", ShortName="Score")]
a) [Authorize(Users = "")]
b) [Authorize(Roles = "")]
c) [Authorize(Users = "*")]
d) [Authorize(Roles = "*")]
<span id="ref">
<a name=Reference>Check out</a>
the FAQ on
<a href="http://www.contoso.com">
Contoso</a>'s web site for more information:
<a href="http://www.contoso.com/faq">FAQ</a>.
</span>
<a href="http://www.contoso.com/home">Home</a>
a) $("#ref").filter("a[href]").bold();
b) $("ref").filter("a").css("bold");
c) $("a").css({fontWeight:"bold"});
d) $("#ref a[href]").css({fontWeight:"bold"});
<div> <h4 class="text-primary pt-3">Attribute Splatting Child Component</h4> <input id="roomName" placeholder="@Placeholder" required="@Required" maxlength="@MaxLength" class="form-control" /> </div> @code { [Parameter] public string Placeholder { get; set; } = "Initial Text"; [Parameter] public string Required { get; set; } = "required"; [Parameter] public string MaxLength { get; set; } = "10"; }
@page "/AttributeSplatting" <h1>Attribute Splatting</h1> <AttributeSplattingChild Placeholder="Enter the Room Name From Parent" MaxLength="5"> </AttributeSplattingChild>
<div> <h4 class="text-primary pt-3">Attribute Splatting Child Component</h4> <input id="roomName" @attributes="InputAttributes" class="form-control" /> </div> @code { [Parameter] public Dictionary<string, object> InputAttributes { get; set; } = new Dictionary<string, object> { { "required" , "required"}, { "placeholder", "Initial Text"}, { "maxlength", 10} }; }
@page "/AttributeSplatting" <h1>Attribute Splatting</h1> <AttributeSplattingChild InputAttributes="InputAttributesFromParent"></AttributeSplattingChild> @code{ Dictionary<string, object> InputAttributesFromParent = new Dictionary<string, object> { { "required" , "required"}, { "placeholder", "Enter the Room Name From Parent"}, { "maxlength", 5} }; }
<div> <h4 class="text-primary pt-3">Attribute Splatting Child Component</h4> <input id="roomName" @attributes="InputAttributes" placeholder="Initial Text" class="form-control" /> </div> @code { [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> InputAttributes { get; set; } = new Dictionary<string, object>(); }
@page "/AttributeSplatting" <h1>Attribute Splatting</h1> <AttributeSplattingChild placeholder="Placeholder default"></AttributeSplattingChild>
<input id="roomName" placeholder="Initial Text" @attributes="InputAttributes" class="form-control" />
<div class="row"> <h4 class="text-primary pl-4 pt-2 col-12">Grand Child Component</h4> <br /> <p> There is a message - @MessageForGrandChild </p> </div> @code { [Parameter] public string MessageForGrandChild { get; set; } }
<div class="mt-2"> <GrandChildComponent MessageForGrandChild="@MessageForGrandChild"></GrandChildComponent> </div> @code { [Parameter] public string MessageForGrandChild { get; set; } // ... }
<ChildComponent MessageForGrandChild="This is a message from Grand Parent" Title="This is the second child component"> <p><b>@MessageText</b></p> </ChildComponent>
<CascadingValue Value="@MessageForGrandChild"> <ChildComponent Title="This is the second child component"> <p><b>@MessageText</b></p> </ChildComponent> </CascadingValue> @code { string MessageForGrandChild = "This is a message from Grand Parent";
<GrandChildComponent></GrandChildComponent>
[CascadingParameter] public string MessageForGrandChild { get; set; }
<CascadingValue Value="@MessageForGrandChild" Name="MessageFromGrandParent"> <CascadingValue Value="@Number" Name="GrandParentsNumber"> <ChildComponent Title="This is the second child component"> <p><b>@MessageText</b></p> </ChildComponent> </CascadingValue> </CascadingValue> @code { string MessageForGrandChild = "This is a message from Grand Parent"; int Number = 7;
<div class="row"> <h4 class="text-primary pl-4 pt-2 col-12">Grand Child Component</h4> <br /> There is a message: @Message <br /> GrandParentsNumber: @Number </div> @code { [CascadingParameter(Name = "MessageFromGrandParent")] public string Message { get; set; } [CascadingParameter(Name = "GrandParentsNumber")] public int Number { get; set; } }
using System.Collections.Generic;
namespace EF_Sample07.DomainClasses { public class Category { public int Id { get; set; } public virtual string Name { get; set; } public virtual string Title { get; set; } public virtual ICollection<Product> Products { get; set; } } }
using System.ComponentModel.DataAnnotations;
namespace EF_Sample07.DomainClasses { public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; }
[ForeignKey("CategoryId")] public virtual Category Category { get; set; } public int CategoryId { get; set; } } }
using System.Data.Entity; using System;
namespace EF_Sample07.DataLayer.Context { public interface IUnitOfWork { IDbSet<TEntity> Set<TEntity>() where TEntity : class; int SaveChanges(); } }
using System.Data.Entity; using EF_Sample07.DomainClasses;
namespace EF_Sample07.DataLayer.Context { public class Sample07Context : DbContext, IUnitOfWork { public DbSet<Category> Categories { set; get; } public DbSet<Product> Products { set; get; }
#region IUnitOfWork Members public new IDbSet<TEntity> Set<TEntity>() where TEntity : class { return base.Set<TEntity>(); } #endregion } }
uow.Set<Product>
using EF_Sample07.DomainClasses; using System.Collections.Generic;
namespace EF_Sample07.ServiceLayer { public interface ICategoryService { void AddNewCategory(Category category); IList<Category> GetAllCategories(); } }
using EF_Sample07.DomainClasses; using System.Collections.Generic;
namespace EF_Sample07.ServiceLayer { public interface IProductService { void AddNewProduct(Product product); IList<Product> GetAllProducts(); } }
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses;
namespace EF_Sample07.ServiceLayer { public class EfCategoryService : ICategoryService { IUnitOfWork _uow; IDbSet<Category> _categories; public EfCategoryService(IUnitOfWork uow) { _uow = uow; _categories = _uow.Set<Category>(); }
public void AddNewCategory(Category category) { _categories.Add(category); }
public IList<Category> GetAllCategories() { return _categories.ToList(); } } }
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses;
namespace EF_Sample07.ServiceLayer { public class EfProductService : IProductService { IUnitOfWork _uow; IDbSet<Product> _products; public EfProductService(IUnitOfWork uow) { _uow = uow; _products = _uow.Set<Product>(); }
public void AddNewProduct(Product product) { _products.Add(product); }
public IList<Product> GetAllProducts() { return _products.Include(x => x.Category).ToList(); } } }
using System.Collections.Generic; using System.Data.Entity; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07 { class Program { static void Main(string[] args) { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>());
HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().CacheBy(InstanceScope.Hybrid).Use<Sample07Context>(); x.For<ICategoryService>().Use<EfCategoryService>(); });
var uow = ObjectFactory.GetInstance<IUnitOfWork>(); var categoryService = ObjectFactory.GetInstance<ICategoryService>();
var product1 = new Product { Name = "P100", Price = 100 }; var product2 = new Product { Name = "P200", Price = 200 }; var category1 = new Category { Name = "Cat100", Title = "Title100", Products = new List<Product> { product1, product2 } }; categoryService.AddNewCategory(category1); uow.SaveChanges(); } } }
public enum InstanceScope { PerRequest = 0, Singleton = 1, ThreadLocal = 2, HttpContext = 3, Hybrid = 4, HttpSession = 5, HybridHttpSession = 6, Unique = 7, Transient = 8, }
using System.Web.Mvc; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer; using EF_Sample07.DataLayer.Context; using System.Collections.Generic;
namespace EF_Sample07.MvcAppSample.Controllers { public class HomeController : Controller { IProductService _productService; ICategoryService _categoryService; IUnitOfWork _uow; public HomeController(IUnitOfWork uow, IProductService productService, ICategoryService categoryService) { _productService = productService; _categoryService = categoryService; _uow = uow; }
[HttpGet] public ActionResult Index() { var list = _productService.GetAllProducts(); return View(list); }
[HttpGet] public ActionResult Create() { ViewBag.CategoriesList = new SelectList(_categoryService.GetAllCategories(), "Id", "Name"); return View(); }
[HttpPost] public ActionResult Create(Product product) { if (this.ModelState.IsValid) { _productService.AddNewProduct(product); _uow.SaveChanges(); }
return RedirectToAction("Index"); }
[HttpGet] public ActionResult CreateCategory() { return View(); }
[HttpPost] public ActionResult CreateCategory(Category category) { if (this.ModelState.IsValid) { _categoryService.AddNewCategory(category); _uow.SaveChanges(); }
return RedirectToAction("Index"); } } }
using System; using System.Data.Entity; using System.Web.Mvc; using System.Web.Routing; using EF_Sample07.DataLayer.Context; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07.MvcAppSample
{ // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); }
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); }
protected void Application_Start() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>()); HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); initStructureMap(); }
private static void initStructureMap() { ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context()); x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>(); x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>(); });
//Set current Controller factory as StructureMapControllerFactory ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); }
protected void Application_EndRequest(object sender, EventArgs e) { ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects(); } }
public class StructureMapControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return ObjectFactory.GetInstance(controllerType) as Controller; } } }
using System; using System.Data.Entity; using EF_Sample07.DataLayer.Context; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07.WebFormsAppSample { public class Global : System.Web.HttpApplication { private static void initStructureMap() { ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context()); x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>(); x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
x.SetAllProperties(y=> { y.OfType<IUnitOfWork>(); y.OfType<ICategoryService>(); y.OfType<IProductService>(); }); }); }
void Application_Start(object sender, EventArgs e) { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>()); HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); initStructureMap(); }
void Application_EndRequest(object sender, EventArgs e) { ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects(); }
using System.Web.UI; using StructureMap;
namespace EF_Sample07.WebFormsAppSample { public class BasePage : Page { public BasePage() { ObjectFactory.BuildUp(this); } } }
using System; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer;
namespace EF_Sample07.WebFormsAppSample { public partial class AddProduct : BasePage { public IUnitOfWork UoW { set; get; } public IProductService ProductService { set; get; } public ICategoryService CategoryService { set; get; }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { bindToCategories(); } }
private void bindToCategories() { ddlCategories.DataTextField = "Name"; ddlCategories.DataValueField = "Id"; ddlCategories.DataSource = CategoryService.GetAllCategories(); ddlCategories.DataBind(); }
protected void btnAdd_Click(object sender, EventArgs e) { var product = new Product { Name = txtName.Text, Price = int.Parse(txtPrice.Text), CategoryId = int.Parse(ddlCategories.SelectedItem.Value) }; ProductService.AddNewProduct(product); UoW.SaveChanges(); Response.Redirect("~/Default.aspx"); } } }
@model ProjectName.ViewModels.Identity.RegisterViewModel <label asp-for="PhoneNumber"></label>
@using System.Reflection @using System.Linq.Expressions @using System.ComponentModel.DataAnnotations @typeparam T @if (ChildContent is null) { <label>@Label</label> } else { <label> @Label @ChildContent </label> } @code { [Parameter, EditorRequired] public Expression<Func<T>> DisplayNameFor { get; set; } = default!; [Parameter] public RenderFragment? ChildContent { get; set; } private string Label => GetDisplayName(); private string GetDisplayName() { var expression = (MemberExpression)DisplayNameFor.Body; var value = expression.Member.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute; return value?.Name ?? expression.Member.Name; } }
private LoginDto Login { get; } = new();
<CustomDisplayName DisplayNameFor="@(() => Login.UserName)" />
<CustomDisplayName DisplayNameFor="@(() => Login.UserName)"> <span class="text-danger">(*)</span> </CustomDisplayName>
@using System.Reflection @using System.Linq.Expressions; @using System.ComponentModel.DataAnnotations; @typeparam T @if (ChildContent == null) { <label>@Label</label> } else { <label> @Label @ChildContent </label> } @code { [Parameter] public Expression<Func<T>> DisplayNameFor { get; set; } = default!; [Parameter] public RenderFragment? ChildContent { get; set; } [Inject] public IStringLocalizerFactory LocalizerFactory { get; set; } = default!; private string Label => GetDisplayName(); private string GetDisplayName() { var expression = (MemberExpression)DisplayNameFor.Body; var displayAttribute = expression.Member.GetCustomAttribute(typeof(DisplayAttribute)) as DisplayAttribute; if (displayAttribute is {ResourceType: not null }) { // Try to dynamically create an instance of the specified resource type var resourceType = displayAttribute.ResourceType; var localizer = LocalizerFactory.Create(resourceType); return localizer[displayAttribute.Name ?? expression.Member.Name]; } return displayAttribute?.Name ?? expression.Member.Name; } }
public class LoginDto { [Display(Name = nameof(LoginDtoResource.UserName), ResourceType = typeof(LoginDtoResource))] [Required] [MaxLength(100)] public string UserName { get; set; } = default!; //... }
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> InputAttributes { get; set; } = new();
@if (ChildContent is null) { <label @attributes="InputAttributes"> @Label </label> } else { <label @attributes="InputAttributes"> @Label @ChildContent </label> }
<CustomDisplayName DisplayNameFor="@(() => Login.UserName)" class="form-label" id="test" for="UserName" />