The object cannot be deleted because it was not found in the ObjectStateManager.
EF Code First #7
The object cannot be deleted because it was not found in the ObjectStateManager.
یک نکتهای رو چند وقت قبل حین کار با ef بهش برخوردم که جالب بود. از دید ef ، کلیدخارجی یا کلید اصلی «فقط خواندنی» هستند. یعنی اگر در اینجا کسی بخواد نام رشته رو تغییر بده مشکل ساز خواهد شد.
به دو دلیل:
- استفاده از رشتهها نسبت به یک عدد چون طولانیتر هستند کندتر است برای حالت تعریف کلید
- اگر تغییری قرار است رخ دهد، باید به تمام جداول اعمال شود. (تعریف اطلاعات تکراری)
colModel: [ { name: 'Name', index: 'Name', align: 'right', width: 200, search: true, stype: 'text', searchoptions: { sopt: searchOptions } }, { name: 'Supplier.Id', index: 'Supplier.Id', align: 'right', width: 200, search: true, stype: 'select', edittype: 'select', searchOperators: true, searchoptions: { sopt: searchOptions, dataUrl: '@Url.Action("SuppliersSelect","Home")' } } ],
var searchOptions = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', 'bw', 'bn', 'in', 'ni', 'ew', 'en', 'cn', 'nc'];
public ActionResult SuppliersSelect() { var list = ProductDataSource.LatestProducts; var suppliers = list.Select(x => new SelectListItem { Text = x.Supplier.CompanyName, Value = x.Supplier.Id.ToString(CultureInfo.InvariantCulture) }).ToList(); return PartialView("_SelectPartial", suppliers); }
@model IList<SelectListItem> @Html.DropDownList("srch", Model)
$(document).ready(function () { $('#list').jqGrid({ // ... مانند قبل و توضیحات فوق }) .jqGrid('navGrid', '#pager', { add: false, edit: false, del: false }, {}, // default settings for edit {}, // default settings for add {}, // delete instead that del:false we need this { // search options multipleSearch: true, closeOnEscape: true, closeAfterSearch: true, ignoreCase: true }) .jqGrid('navButtonAdd', "#pager", { caption: "نوار ابزار جستجو", title: "Search Toolbar", buttonicon: 'ui-icon-search', onClickButton: function () { toolbarSearching(); } }); }); function toolbarSearching() { $('#list').filterToolbar({ groupOp: 'OR', defaultSearch: "cn", autosearch: true, searchOnEnter: true, searchOperators: true, // فعال سازی منوی اپراتورها stringResult : true // وجود این سطر سبب میشود تا اپراتورها به سرور ارسال شوند }); }; function singleSearching() { $('#list').searchGrid({ closeAfterSearch: true }); }; function advancedSearching() { $('#list').searchGrid({ multipleSearch: true, closeAfterSearch: true }); };
/* align center search popup in jqgrid */ .ui-jqdialog { display: none; width: 300px; position: absolute; padding: .2em; font-size: 11px; overflow: visible; left: 30% !important; top: 40% !important; }
//single field search //_search=true&nd=1403935889318&rows=10&page=1&sidx=Id&sord=asc&searchField=Id&searchString=4444&searchOper=eq&filters= //multi-field search //_search=true&nd=1403935941367&rows=10&page=1&sidx=Id&sord=asc&filters=%7B%22groupOp%22%3A%22AND%22%2C%22rules%22%3A%5B%7B%22field%22%3A%22Id%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%2244%22%7D%2C%7B%22field%22%3A%22SupplierID%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%221%22%7D%5D%7D&searchField=&searchString=&searchOper= // filters -> {"groupOp":"AND","rules":[{"field":"All","op":"cn","data":"fffff"},{"field":"Price","op":"bn","data":"ffff"}]} //toolbar search //_search=true&nd=1403935593036&rows=10&page=1&sidx=Id&sord=asc&Id=2&Name=333&SupplierID=1&CategoryID=1&Price=44
{ "groupOp": "AND", "groups" : [ { "groupOp": "OR", "rules": [ { "field": "name", "op": "eq", "data": "England" }, { "field": "id", "op": "le", "data": "5"} ] } ], "rules": [ { "field": "name", "op": "eq", "data": "Romania" }, { "field": "id", "op": "le", "data": "1"} ] }
public class SearchFilter { public string groupOp { set; get; } public List<SearchGroup> groups { set; get; } public List<SearchRule> rules { set; get; } } public class SearchRule { public string field { set; get; } public string op { set; get; } public string data { set; get; } public override string ToString() { return string.Format("'{0}' {1} '{2}'", field, op, data); } } public class SearchGroup { public string groupOp { set; get; } public List<SearchRule> rules { set; get; } }
public IQueryable<T> ApplyFilter<T>(IQueryable<T> query, bool _search, string searchField, string searchString, string searchOper, string filters, NameValueCollection form)
[HttpPost] public ActionResult GetProducts(string sidx, string sord, int page, int rows, bool _search, string searchField, string searchString, string searchOper, string filters) { var list = ProductDataSource.LatestProducts; var pageIndex = page - 1; var pageSize = rows; var totalRecords = list.Count; var totalPages = (int)Math.Ceiling(totalRecords / (float)pageSize); var productsQuery = list.AsQueryable(); productsQuery = new JqGridSearch().ApplyFilter(productsQuery, _search, searchField, searchString, searchOper, filters, this.Request.Form); var productsList = productsQuery.OrderBy(sidx + " " + sord) .Skip(pageIndex * pageSize) .Take(pageSize) .ToList(); var productsData = new JqGridData { Total = totalPages, Page = page, Records = totalRecords, Rows = (productsList.Select(product => new JqGridRowData { Id = product.Id, RowCells = new List<string> { product.Id.ToString(CultureInfo.InvariantCulture), product.Name, product.Supplier.CompanyName, product.Category.Name, product.Price.ToString(CultureInfo.InvariantCulture) } })).ToArray() }; return Json(productsData, JsonRequestBehavior.AllowGet); }
$('#list').jqGrid({ //url access method type mtype: 'POST',
productsQuery = new JqGridSearch().ApplyFilter(productsQuery, _search, searchField, searchString, searchOper, filters, this.Request.Form);
[AllowAnonymous] [IgnoreAntiforgeryToken] [HttpPost("[action]")] public async Task<IActionResult> Login([FromBody] User loginUser)
private void regenerateAntiForgeryCookie(IEnumerable<Claim> claims) { this.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme)); var tokens = _antiforgery.GetAndStoreTokens(this.HttpContext); this.HttpContext.Response.Cookies.Append( key: "XSRF-TOKEN", value: tokens.RequestToken, options: new CookieOptions { HttpOnly = false // Now JavaScript is able to read the cookie }); }
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString(), ClaimValueTypes.String, _configuration.Value.Issuer),
public enum CommentType { Article, Video, Event } public class Comment { public int Id { get; set; } public string CommentText { get; set; } public string User { get; set; } public int? TypeId { get; set; } public CommentType CommentType { get; set; } } public class Article { public int Id { get; set; } public string Title { get; set; } public string Slug { get; set; } public string Description { get; set; } } public class Video { public int Id { get; set; } public string Url { get; set; } public string Description { get; set; } } public class Event { public int Id { get; set; } public string Name { get; set; } public DateTimeOffset? Start { get; set; } public DateTimeOffset? End { get; set; } } public class MyDbContext : DbContext { public DbSet<Article> Articles { get; set; } public DbSet<Video> Videos { get; set; } public DbSet<Event> Events { get; set; } public DbSet<Comment> Comments { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=polymorphic.db"); }
var articleComments = dbContext.Comments .Where(x => x.CommentType == CommentType.Article && x.TypeId.Value == 1); foreach (var articleComment in articleComments) { Console.WriteLine(articleComment.CommentText); }
public class Comment { public int Id { get; set; } public string CommentText { get; set; } public string User { get; set; } public virtual ICollection<ArticleComment> ArticleComments { get; set; } public virtual ICollection<VideoComment> VideoComments { get; set; } public virtual ICollection<EventComment> EventComments { get; set; } } public class Article { public Article() { ArticleComments = new HashSet<ArticleComment>(); } public int Id { get; set; } public string Title { get; set; } public string Slug { get; set; } public string Description { get; set; } public virtual ICollection<ArticleComment> ArticleComments { get; set; } } public class Video { public Video() { VideoComments = new HashSet<VideoComment>(); } public int Id { get; set; } public string Url { get; set; } public string Description { get; set; } public virtual ICollection<VideoComment> VideoComments { get; set; } } public class Event { public Event() { EventComments = new HashSet<EventComment>(); } public int Id { get; set; } public string Name { get; set; } public DateTimeOffset? Start { get; set; } public DateTimeOffset? End { get; set; } public virtual ICollection<EventComment> EventComments { get; set; } } public class MyDbContext : DbContext { public DbSet<Article> Articles { get; set; } public DbSet<ArticleComment> ArticleComments { get; set; } public DbSet<Video> Videos { get; set; } public DbSet<VideoComment> VideoComments { get; set; } public DbSet<Event> Events { get; set; } public DbSet<EventComment> EventComments { get; set; } public DbSet<Comment> Comments { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=polymorphic.db"); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ArticleComment>(entity => { entity.HasKey(e => new { e.CommentId, e.ArticleId }) .HasName("PK_dbo.ArticleComments"); entity.HasIndex(e => e.ArticleId) .HasName("IX_ArticleId"); entity.HasIndex(e => e.CommentId) .HasName("IX_ArticleCommentId"); entity.HasOne(d => d.Article) .WithMany(p => p.ArticleComments) .HasForeignKey(d => d.ArticleId) .HasConstraintName("FK_dbo.ArticleComments_dbo.Articles_ArticleId"); entity.HasOne(d => d.Comment) .WithMany(p => p.ArticleComments) .HasForeignKey(d => d.CommentId) .HasConstraintName("FK_dbo.ArticleComments_dbo.Comments_CommentId"); }); modelBuilder.Entity<VideoComment>(entity => { entity.HasKey(e => new { e.CommentId, e.VideoId }) .HasName("PK_dbo.VideoComments"); entity.HasIndex(e => e.VideoId) .HasName("IX_VideoId"); entity.HasIndex(e => e.CommentId) .HasName("IX_VideoCommentId"); entity.HasOne(d => d.Video) .WithMany(p => p.VideoComments) .HasForeignKey(d => d.VideoId) .HasConstraintName("FK_dbo.VideoComments_dbo.Videos_VideoId"); entity.HasOne(d => d.Comment) .WithMany(p => p.VideoComments) .HasForeignKey(d => d.CommentId) .HasConstraintName("FK_dbo.VideoComments_dbo.Comments_CommentId"); }); modelBuilder.Entity<EventComment>(entity => { entity.HasKey(e => new { e.CommentId, e.EventId }) .HasName("PK_dbo.EventComments"); entity.HasIndex(e => e.EventId) .HasName("IX_EventId"); entity.HasIndex(e => e.CommentId) .HasName("IX_EventCommentId"); entity.HasOne(d => d.Event) .WithMany(p => p.EventComments) .HasForeignKey(d => d.EventId) .HasConstraintName("FK_dbo.EventComments_dbo.Events_EventId"); entity.HasOne(d => d.Comment) .WithMany(p => p.EventComments) .HasForeignKey(d => d.CommentId) .HasConstraintName("FK_dbo.EventComments_dbo.Comments_CommentId"); }); } }
var article = new Article { Title = "Article A", Slug = "article_a", Description = "No Description" }; var comment = new Comment { CommentText = "It's great", User = "Sirwan" }; dbContext.ArticleComments.Add(new ArticleComment { Article = article, Comment = comment }); dbContext.SaveChanges(); var articleOne = dbContext.Articles .Include(article => article.ArticleComments) .ThenInclude(comment => comment.Comment) .First(article => article.Id == 1); var article1Comments = articleOne.ArticleComments.Select(x => x.Comment); Console.WriteLine(article1Comments.Count());
public class Comment { public int Id { get; set; } public string CommentText { get; set; } public string User { get; set; } // Article public virtual Article Article { get; set; } public int? ArticleId { get; set; } // Video public virtual Video Video { get; set; } public int? VideoId { get; set; } // Event public virtual Event Event { get; set; } public int? EventId { get; set; } } public class Article { public int Id { get; set; } public string Title { get; set; } public string Slug { get; set; } public string Description { get; set; } public virtual ICollection<Comment> Comments { get; set; } } public class Video { public int Id { get; set; } public string Url { get; set; } public string Description { get; set; } public virtual ICollection<Comment> Comments { get; set; } } public class Event { public int Id { get; set; } public string Name { get; set; } public DateTimeOffset? Start { get; set; } public DateTimeOffset? End { get; set; } public virtual ICollection<Comment> Comments { get; set; } } public class MyDbContext : DbContext { public DbSet<Article> Articles { get; set; } public DbSet<Video> Videos { get; set; } public DbSet<Event> Events { get; set; } public DbSet<Comment> Comments { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=polymorphic.db"); }
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Comment>(entity => entity.HasCheckConstraint("CHECK_FKs", "(`ArticleId` IS NOT NULL) AND (`VideoId` IS NOT NULL) AND (`EventId` IS NOT NULL)")); }
var articles = dbContext.Articles .Include(x => x.Comments).Where(x => x.Id == 1); foreach (var article in articles) { Console.WriteLine($"{article.Title} - Comments: {article.Comments.Count}"); } var comment = dbContext.Comments.Include(x => x.Article) .FirstOrDefault(x => x.Id == 1); Console.WriteLine(comment?.Article.Title);
[PageAuthorization(AuthorizationType.ApplyRequiredRoles, "IsAdmin, CanAddNewUser")]
/// <summary> /// وضعیت اعتبار سنجی صفحه را مشخص میکند /// </summary> public enum AuthorizationType { /// <summary> /// همه میتوانند بدون اعتبار سنجی، دسترسی به این صفحات داشته باشند /// </summary> AllowAnonymous, /// <summary> /// کاربران وارد شده به سیستم بدون محدودیت به این صفحات دسترسی خواهند داشت /// </summary> FreeForAuthenticatedUsers, /// <summary> /// بر اساس نام نقشهایی که مشخص میشوند تصمیم گیری خواهد شد /// </summary> ApplyRequiredRoles }
[ImplementPropertyChanged] // AOP public class LoginPageModel : DataErrorInfoBase
dotnet new worker
<Project Sdk="Microsoft.NET.Sdk.Worker"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <UserSecretsId>dotnet-MyWorkerServiceApp-B76DB08E-FFBB-4AD1-89B5-93BF483D1BD0</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0-preview8.19405.4" /> </ItemGroup> </Project>
namespace MyWorkerServiceApp { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); }); } }
public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; public Worker(ILogger<Worker> logger) { _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); } } }
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseWindowsService() .ConfigureServices((hostContext, services) => { //services.AddHttpClient(); services.AddHostedService<Worker>(); });
cs create WorkerServiceDemo binPath=C:\Path\To\WorkerServiceDemo.exe
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSystemd() .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); });