EF Code First 11 و EF Code First 12 در مورد دایرکتوریهای Contracts و EFServiecs توضیح داده. دوره فریم ورک WPF هم این پوشه بندیها رو بیشتر توضیح داده.
پاسخ به بازخوردهای پروژهها
protected override void Dispose(bool disposing) { if (disposing) { if (this.wrappedConnection != null) this.wrappedConnection.Dispose(); } base.Dispose(disposing); }
using System; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.Entity.Migrations; using System.Diagnostics; using System.Linq; using EFTracingProvider; namespace Sample { public class Person { public int Id { get; set; } public string Name { get; set; } } public class Configuration : DbMigrationsConfiguration<MyContext> { public Configuration() { var className = this.ContextType.FullName; var connectionStringData = ConfigurationManager.ConnectionStrings[className]; if (connectionStringData == null) throw new InvalidOperationException(string.Format("ConnectionStrings[{0}] not found.", className)); TargetDatabase = new DbConnectionInfo(connectionStringData.ConnectionString, connectionStringData.ProviderName); AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyContext context) { for (int i = 0; i < 7; i++) context.Users.Add(new Person { Name = "name " + i }); base.Seed(context); } } public class MyContext : MyLoggedContext { public DbSet<Person> Users { get; set; } } public abstract class MyLoggedContext : DbContext { protected MyLoggedContext() : base(existingConnection: createConnection(), contextOwnsConnection: true) { var ctx = ((IObjectContextAdapter)this).ObjectContext; ctx.GetTracingConnection().CommandExecuting += (s, e) => { Console.WriteLine("{0}\n", e.ToTraceString()); }; } private static DbConnection createConnection() { var st = new StackTrace(); var sf = st.GetFrame(2); // Get the derived class Type in a base class static method var className = sf.GetMethod().DeclaringType.FullName; var connectionStringData = ConfigurationManager.ConnectionStrings[className]; if (connectionStringData == null) throw new InvalidOperationException(string.Format("ConnectionStrings[{0}] not found.", className)); if (!isEFTracingProviderRegistered()) EFTracingProviderConfiguration.RegisterProvider(); EFTracingProviderConfiguration.LogToFile = "log.sql"; var wrapperConnectionString = string.Format(@"wrappedProvider={0};{1}", connectionStringData.ProviderName, connectionStringData.ConnectionString); return new EFTracingConnection { ConnectionString = wrapperConnectionString }; } private static bool isEFTracingProviderRegistered() { var data = (DataSet)ConfigurationManager.GetSection("system.data"); var providerFactories = data.Tables["DbProviderFactories"]; return providerFactories.Rows.Cast<DataRow>() .Select(row => (string)row.ItemArray[1]) .Any(invariantName => invariantName == "EF Tracing Data Provider"); } } public static class Test { public static void RunTests() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>()); using (var ctx = new MyContext()) { var users = ctx.Users.AsEnumerable(); if (users.Any()) { foreach (var user in users) { Console.WriteLine(user.Name); } } var rnd = new Random(); var user1 = ctx.Users.Find(1); user1.Name = "test user " + rnd.Next(); ctx.SaveChanges(); } } } }
public class MyContext : MyLoggedContext
insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 0" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 1" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 2" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 3" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 4" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 5" insert [dbo].[People]([Name]) values (@0) select [Id] from [dbo].[People] where @@ROWCOUNT > 0 and [Id] = scope_identity() -- @0 (dbtype=String, size=-1, direction=Input) = "name 6" SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name] FROM [dbo].[People] AS [Extent1] SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name] FROM [dbo].[People] AS [Extent1] name 0 name 1 name 2 name 3 name 4 name 5 name 6 update [dbo].[People] set [Name] = @0 where ([Id] = @1) -- @0 (dbtype=String, size=-1, direction=Input) = "test user 1355460609" -- @1 (dbtype=Int32, size=0, direction=Input) = 1
CREATE TABLE cd.members ( memid integer NOT NULL, surname character varying(200) NOT NULL, firstname character varying(200) NOT NULL, address character varying(300) NOT NULL, zipcode integer NOT NULL, telephone character varying(20) NOT NULL, recommendedby integer, joindate timestamp not null, CONSTRAINT members_pk PRIMARY KEY (memid), CONSTRAINT fk_members_recommendedby FOREIGN KEY (recommendedby) REFERENCES cd.members(memid) ON DELETE SET NULL );
CREATE TABLE cd.facilities ( facid integer NOT NULL, name character varying(100) NOT NULL, membercost numeric NOT NULL, guestcost numeric NOT NULL, initialoutlay numeric NOT NULL, monthlymaintenance numeric NOT NULL, CONSTRAINT facilities_pk PRIMARY KEY (facid) );
CREATE TABLE cd.bookings ( bookid integer NOT NULL, facid integer NOT NULL, memid integer NOT NULL, starttime timestamp NOT NULL, slots integer NOT NULL, CONSTRAINT bookings_pk PRIMARY KEY (bookid), CONSTRAINT fk_bookings_facid FOREIGN KEY (facid) REFERENCES cd.facilities(facid), CONSTRAINT fk_bookings_memid FOREIGN KEY (memid) REFERENCES cd.members(memid) );
namespace EFCorePgExercises.Entities { public class Member { public int MemId { set; get; } public string Surname { set; get; } public string FirstName { set; get; } public string Address { set; get; } public int ZipCode { set; get; } public string Telephone { set; get; } public virtual ICollection<Member> Children { get; set; } public virtual Member Recommender { set; get; } public int? RecommendedBy { set; get; } public DateTime JoinDate { set; get; } public virtual ICollection<Booking> Bookings { set; get; } } }
namespace EFCorePgExercises.Entities { public class Facility { public int FacId { set; get; } public string Name { set; get; } public decimal MemberCost { set; get; } public decimal GuestCost { set; get; } public decimal InitialOutlay { set; get; } public decimal MonthlyMaintenance { set; get; } public virtual ICollection<Booking> Bookings { set; get; } } }
namespace EFCorePgExercises.Entities { public class Booking { public int BookId { set; get; } public int FacId { set; get; } public virtual Facility Facility { set; get; } public int MemId { set; get; } public virtual Member Member { set; get; } public DateTime StartTime { set; get; } public int Slots { set; get; } } }
namespace EFCorePgExercises.Entities { public class MemberConfiguration : IEntityTypeConfiguration<Member> { public void Configure(EntityTypeBuilder<Member> builder) { builder.HasKey(member => member.MemId); builder.Property(member => member.MemId).IsRequired().UseIdentityColumn(seed: 0, increment: 1); builder.Property(member => member.Surname).HasMaxLength(200).IsRequired(); builder.Property(member => member.FirstName).HasMaxLength(200).IsRequired(); builder.Property(member => member.Address).HasMaxLength(300).IsRequired(); builder.Property(member => member.ZipCode).IsRequired(); builder.Property(member => member.Telephone).HasMaxLength(20).IsRequired(); builder.HasIndex(member => member.RecommendedBy); builder.HasOne(member => member.Recommender) .WithMany(member => member.Children) .HasForeignKey(member => member.RecommendedBy); builder.Property(member => member.JoinDate).IsRequired(); builder.HasIndex(member => member.JoinDate).HasName("IX_JoinDate"); builder.HasIndex(member => member.RecommendedBy).HasName("IX_RecommendedBy"); } } }
namespace EFCorePgExercises.Entities { public class FacilityConfiguration : IEntityTypeConfiguration<Facility> { public void Configure(EntityTypeBuilder<Facility> builder) { builder.HasKey(facility => facility.FacId); builder.Property(facility => facility.FacId).IsRequired().UseIdentityColumn(seed: 0, increment: 1); builder.Property(facility => facility.Name).HasMaxLength(100).IsRequired(); builder.Property(facility => facility.MemberCost).IsRequired().HasColumnType("decimal(18, 6)"); builder.Property(facility => facility.GuestCost).IsRequired().HasColumnType("decimal(18, 6)"); builder.Property(facility => facility.InitialOutlay).IsRequired().HasColumnType("decimal(18, 6)"); builder.Property(facility => facility.MonthlyMaintenance).IsRequired().HasColumnType("decimal(18, 6)"); } } }
namespace EFCorePgExercises.Entities { public class BookingConfiguration : IEntityTypeConfiguration<Booking> { public void Configure(EntityTypeBuilder<Booking> builder) { builder.HasKey(booking => booking.BookId); builder.Property(booking => booking.BookId).IsRequired().UseIdentityColumn(seed: 0, increment: 1); builder.Property(booking => booking.FacId).IsRequired(); builder.HasOne(booking => booking.Facility) .WithMany(facility => facility.Bookings) .HasForeignKey(booking => booking.FacId); builder.Property(booking => booking.MemId).IsRequired(); builder.HasOne(booking => booking.Member) .WithMany(member => member.Bookings) .HasForeignKey(booking => booking.MemId); builder.Property(booking => booking.StartTime).IsRequired(); builder.Property(booking => booking.Slots).IsRequired(); builder.HasIndex(booking => new { booking.MemId, booking.FacId }).HasName("IX_memid_facid"); builder.HasIndex(booking => new { booking.FacId, booking.StartTime }).HasName("IX_facid_starttime"); builder.HasIndex(booking => new { booking.MemId, booking.StartTime }).HasName("IX_memid_starttime"); builder.HasIndex(booking => booking.StartTime).HasName("IX_starttime"); } } }
namespace EFCorePgExercises.DataLayer { public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } public DbSet<Member> Members { get; set; } public DbSet<Booking> Bookings { get; set; } public DbSet<Facility> Facilities { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfigurationsFromAssembly(typeof(MemberConfiguration).Assembly); } } }
dotnet tool install --global dotnet-ef --version 3.1.6 dotnet tool update --global dotnet-ef --version 3.1.6 dotnet build dotnet ef migrations add Init --context ApplicationDbContext
context.Facilities.Add(new Facility { Name = "Tennis Court 1", MemberCost = 5, GuestCost = 25, InitialOutlay = 10000, MonthlyMaintenance = 200 }); // مابقی موارد context.SaveChanges();
context.Members.Add(new Member { ... }); context.SaveChanges(); // For id = 0 = Int's CLR Default Value!
using (var transaction = context.Database.BeginTransaction()) { try { context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Members ON"); context.Members.Add(new Member { ... }); // مابقی موارد context.SaveChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } finally { context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Members OFF"); } }
public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel> { public IText _text { get; set; } public Localizer T { get { return _text.Get; } } public override void InitHelpers() { //_text = ProjectObjectFactory.Container.GetInstance<Text>(); base.InitHelpers(); } } public abstract class WebViewPage : WebViewPage<dynamic> { } }
public class TestRegistry : Registry { public TestRegistry() { // Policies.FillAllPropertiesOfType<IText>().Use<Text>(); For<IText>().Use<Text>(); Policies.SetAllProperties(x => { x.OfType<IText>(); }); } }
public class BaseEntity { public DateTimeOffset CreatedDate { get; set; } public DateTimeOffset UpdatedDate { get; set; } }
//override because we need add created and updated date to some entities public override async Task<int> SaveChangesAsync( CancellationToken cancellationToken = default(CancellationToken)) { AddCreatedUpdatedDate(); return (await base.SaveChangesAsync(true, cancellationToken)); } //override because we need add created and updated date to some entities public override int SaveChanges() { AddCreatedUpdatedDate(); return base.SaveChanges(); }
/// <summary> /// Add created and updated date to any entities that /// inherit from BaseEntity class /// </summary> public void AddCreatedUpdatedDate() { var entries = ChangeTracker .Entries() .Where(e => e.Entity is BaseEntity && ( e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entityEntry in entries) { ((BaseEntity)entityEntry.Entity).UpdatedDate = DateTimeOffset.UtcNow; if (entityEntry.State == EntityState.Added) { ((BaseEntity)entityEntry.Entity).CreatedDate = DateTimeOffset.UtcNow; } } }
public class Student: BaseEntity { public int StudentID { get; set; } public string StudentName { get; set; } public DateTimeOffset? DateOfBirth { get; set; } public decimal Height { get; set; } public float Weight { get; set; } }
public interface IFoo { IPerson Person { get; } ICompany Company { get; } DateTime Date { get; } long NormalShareCount { get; } } public interface IPerson { string Name{get;} } public interface ICompany { string Name{get;} }
public class Navbar { public int Id { get; set; } public string Title { get; set; } public int? ParentId { get; set; } public virtual Navbar Parent { get; set; } public bool IsActive { get; set; } public bool HasChiled { get; set; } public bool IsMegaMenu { get; set; } public PageGroup PageGroup { get; set; } public string Url { get; set; } public bool OpenNewPage { get; set; } public virtual ICollection<Navbar> Children { get; set; } }
public class TopNavbar : ViewComponent { private readonly DbSet<Navbar> _navbars; private readonly AppDbContext _dbContext; public TopNavbar(AppDbContext dbContext) { _dbContext = dbContext; _navbars = _dbContext.Set<Navbar>(); } public async Task<IViewComponentResult> InvokeAsync() { var navbars = await _navbars.Include(p=>p.Parent).Include(x=>x.Children).OrderBy(x=>x.ParentId).ToListAsync(); return View(viewName: "~/Views/Shared/Components/NavbarViewComponent/_Menu.cshtml", navbars); } }
<ul class="menu"> <li> <a href="Index_demo6.html"><i class="menu_icon_wrapper fal fa-home-lg-alt"></i>صفحه اصلی</a> </li> @await Component.InvokeAsync("TopNavbar"); </ul>
@using TR.Context.Entities @using Microsoft.AspNetCore.Html @model IEnumerable<TR.Context.Entities.Navbar> @foreach (var menu in Model.Where(x => x.Parent == null)) { <li class="@(menu.HasChiled ? "has_sub narrow" : "")"> <a href="#">@menu.Title</a> @if (menu.HasChiled) { <div class="second"> <div class="inner"> <ul> @foreach (var menuChild in menu.Children) { <partial name="~/Views/Shared/Components/NavbarViewComponent/_SubMenu.cshtml" model="menuChild" /> } </ul> </div> </div> } </li> }
@model TR_.Context.Entities.Navbar <li class="@(Model.HasChiled ? "sub":"")"> <a href="#"> @if (Model.Children.Any()) {<i class="q_menu_arrow fal fa-angle-left"></i>} @Model.Title </a> @if (Model.Children.Any()) { <ul> @foreach (var menuChild in Model.Children) { <partial name="~/Views/Shared/Components/NavbarViewComponent/_SubMenu.cshtml" model="menuChild" /> } </ul> } </li>
with Cacheable:
ساختار موجودیت در DomainLayer :
public class PublicMenu : BaseEntity { public PublicMenu() { SubMenus = new List<PublicMenu>(); } public string Title { get; set; } public string Url { get; set; } public string Icon { get; set; } public bool IsShow { get; set; } public virtual PublicMenu Menu { set; get; } public int? MenuId { get; set; } public ICollection<PublicMenu> SubMenus { get; set; } }
TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory);
var dictionary = new ConcurrentDictionary<string, string>(); var value = dictionary.GetOrAdd("key1", x => "item 1"); Console.WriteLine(value); value = dictionary.GetOrAdd("key1", x => "item 2"); Console.WriteLine(value);
item 1 item 1
using System; using System.Collections.Concurrent; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { var dictionary = new ConcurrentDictionary<int, int>(); var options = new ParallelOptions { MaxDegreeOfParallelism = 100 }; var addStack = new ConcurrentStack<int>(); Parallel.For(1, 1000, options, i => { var key = i % 10; dictionary.GetOrAdd(key, k => { addStack.Push(k); return i; }); }); Console.WriteLine($"dictionary.Count: {dictionary.Count}"); Console.WriteLine($"addStack.Count: {addStack.Count}"); } } }
dictionary.Count: 10 addStack.Count: 13
// 'GetOrAdd' call on the dictionary is not thread safe and we might end up creating the pipeline more // once. To prevent this Lazy<> is used. In the worst case multiple Lazy<> objects are created for multiple // threads but only one of the objects succeeds in creating a pipeline. private readonly ConcurrentDictionary<Type, Lazy<RequestDelegate>> _pipelinesCache = new ConcurrentDictionary<Type, Lazy<RequestDelegate>>();
namespace Sample { class Program { static void Main(string[] args) { var dictionary = new ConcurrentDictionary<int, Lazy<int>>(); var options = new ParallelOptions { MaxDegreeOfParallelism = 100 }; var addStack = new ConcurrentStack<int>(); Parallel.For(1, 1000, options, i => { var key = i % 10; dictionary.GetOrAdd(key, k => new Lazy<int>(() => { addStack.Push(k); return i; })); }); // Access the dictionary values to create lazy values. foreach (var pair in dictionary) Console.WriteLine(pair.Value.Value); Console.WriteLine($"dictionary.Count: {dictionary.Count}"); Console.WriteLine($"addStack.Count: {addStack.Count}"); } } }
10 1 2 3 4 5 6 7 8 9 dictionary.Count: 10 addStack.Count: 10
public class LazyConcurrentDictionary<TKey, TValue> { private readonly ConcurrentDictionary<TKey, Lazy<TValue>> _concurrentDictionary; public LazyConcurrentDictionary() { _concurrentDictionary = new ConcurrentDictionary<TKey, Lazy<TValue>>(); } public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) { var lazyResult = _concurrentDictionary.GetOrAdd(key, k => new Lazy<TValue>(() => valueFactory(k), LazyThreadSafetyMode.ExecutionAndPublication)); return lazyResult.Value; } }