我使用EF4 DbContext为ASP.NET MVC应用程序提供模型.我使用ViewModels为视图和Automapper提供数据,以执行EF POCO和ViewModel之间的映射.Automapper做得很好,但在将ViewModel发回控制器进行更新后,我不清楚使用它的最佳方法.
我的想法是使用ViewModel中包含的密钥获取POCO对象.然后,我想使用Automapper使用ViewModel中的数据更新POCO:
[HttpPost]
public ActionResult Edit(PatientView viewModel)
{
Patient patient = db.Patients.Find(viewModel.Id);
patient = Mapper.Map<ViewModel, Patient>(viewModel, patient);
...
db.SaveChanges();
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
两个问题:
asp.net-mvc viewmodel automapper entity-framework-4 dbcontext
我在互联网上找不到答案.
假设我有一个DbContext,我只是从中选择所有实体.我不添加,更新或删除任何实体DbSet.
如果我SaveChanges事后打电话给DbSet.它是否真的浪费资源建立连接和其他东西即使我没有做任何改变DbSet?
是否足够智能来检测是否进行了更改,并且行为方式不同?
我有一个问题,EF 4.1没有调用,OnModelCreating所以我可以配置表等我有一个现有的数据库.这是我的连接字符串:
<add name="AcmeDBContext"
connectionString="metadata=res://*/|res://*/|res://*/;
provider=System.Data.SqlClient;
provider connection string="
data source=[server];
initial catalog=Acme;integrated security=True;
multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
Run Code Online (Sandbox Code Playgroud)
这是我的继承自的类DbContext:
public class AcmeDBContext : DbContext
{
public AcmeDBContext()
: base()
{
Database.SetInitializer<AcmeDBContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Vehicle>().ToTable("tblVehicle");
modelBuilder.Entity<VehicleMake>().ToTable("tblVehicleMake");
modelBuilder.Entity<VehicleModel>().ToTable("tblVehicleModel");
base.OnModelCreating(modelBuilder);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经在线阅读和阅读,但我不能指出问题所在.该OnModelCreating不会被调用,因此例外说,实体/类(汽车,VehicleMake,VehicleModel)不会在目前情况下存在,当我试图查询任何东西.
我正在使用DbContext基于Generic Repositories和Unit of Work设计模式创建的代码中的类.(我在这里遵循指导.)在这个项目上工作时,我遇到了这个ObjectContext课程.
我读过相当数量的讨论帖子ObjectContext对DbContext.虽然我读过的一些内容是有道理的,但我仍然没有完全理解这些差异,这让我对我当前的实现感到疑惑.我应该使用DbContext,ObjectContext还是两者兼而有之?使用其中一个现在被认为是反模式?
有一定的背景可以通过这个 - 请忍受我!
我们有一个使用EF的n层WPF应用程序 - 我们通过dbContext将数据从数据库加载到POCO类中.销毁dbContext,然后用户就可以编辑数据.我们使用Julie Lerman在她的书"Programming Entity Framework:DBContext"中建议的"状态绘画",这样当我们将根实体添加到新的dbContext进行保存时,我们可以设置是否添加,修改或保持每个子实体等等. .
当我们第一次这样做时(早在2012年11月!)我们遇到的问题是,如果我们添加到dbContext的根实体具有相同子实体的多个实例(即,链接到用户的"任务"记录, "状态历史记录"也链接到同一用户)进程将失败,因为即使子实体是相同的(来自相同的数据库行),它们也被赋予不同的哈希码,因此EF将它们识别为不同的对象.
我们修复了这个问题(早在2012年12月!),通过在我们的实体上覆盖GetHashCode,如果实体来自数据库,则返回数据库ID,如果实体尚未保存,则返回唯一的负数.现在,当我们将根实体添加到dbContext时,它足够聪明,可以实现多次添加相同的子实体并正确处理它.自2012年12月以来我们一直运作良好,直到我们上周升级到EF6 ...
EF6的一个新"功能"是它现在使用它自己的Equals和GetHashCode方法来执行更改跟踪任务,忽略任何自定义覆盖.请参阅:http://msdn.microsoft.com/en-us/magazine/dn532202.aspx(搜索"减少对编码风格的干扰").如果您希望EF管理变更跟踪,那么这很好,但在断开连接的n层应用程序中,我们不希望这样做,实际上这会破坏我们的代码,这些代码已经运行了一年多.
希望这是有道理的.
现在 - 问题 - 有没有人知道我们可以告诉EF6如何在EF5中使用我们的 GetHashCode和Equals方法,或者是否有人有更好的方法来处理将根实体添加到具有重复子实体的dbContext在它,以便EF6会满意吗?
谢谢你的帮助.对不起,很长的帖子.
更新 已经在EF代码中探讨了它看起来像是通过获取实体的哈希码来设置InternalEntityEntry(dbEntityEntry)的哈希码,但现在在EF6中使用RuntimeHelpers.GetHashCode(_entity)检索,这意味着我们被覆盖实体上的哈希码被忽略.所以我想让EF6使用我们的哈希码是不可能的,所以我可能需要专注于如何将实体添加到可能具有重复子实体的上下文而不会扰乱EF.有什么建议?
更新2 最烦人的事情是,这种功能上的变化被报告为一件好事,而不是,正如我所看到的那样,这是一个突破性的变化!当然,如果你有断开连接的实体,并且你已经为它们加载.AsNoTracking()以获得性能(并且因为我们知道我们将断开它们,所以为什么还要跟踪它们),那么dbContext没有理由覆盖我们的getHashcode方法!
更新3 感谢所有的意见和建议 - 非常感谢!经过一些实验,它似乎与.AsNoTracking()有关.如果使用.AsNoTracking()加载数据,则重复的子实体是内存中的单独对象(具有不同的哈希码),因此存在状态绘制问题并在以后保存它们.我们之前通过覆盖哈希码修复了这个问题,因此当实体被添加回保存上下文时,重复的实体被识别为同一个对象,并且只添加一次,但我们不能再使用EF6执行此操作.所以现在我需要进一步研究为什么我们首先使用.AsNoTracking().另外一个想法是,EF6的更改跟踪器应该只对其主动跟踪的条目使用自己的哈希码生成方法 - 如果实体已经加载了.AsNoTracking(),它可能应该使用来自底层实体的哈希码吗?
更新4
现在我们已经确定我们不能继续在EF6中使用我们的方法(重写的哈希码和.AsNoTracking),我们应该如何管理对断开连接的实体的更新?我用blogposts/comments/authors创建了这个简单的例子:

在此示例中,我想打开blogpost 1,更改内容和作者,然后再次保存.我已经尝试了3种方法与EF6,我无法让它工作:
BlogPost blogpost;
using (TestEntities te = new TestEntities())
{
te.Configuration.ProxyCreationEnabled = false;
te.Configuration.LazyLoadingEnabled = false;
//retrieve blog post 1, with all comments and authors
//(so we can display the entire record on the UI while we …Run Code Online (Sandbox Code Playgroud) 在Visual Studio 2013中,在创建ASP.NET项目时,它会生成一个文件IdentityModels.cs,其中包含一个ApplicationDbContext继承自的类,该类IdentityDbContext<ApplicationUser>最终继承自DbContext.
我应该仅为帐户相关实体保留此上下文,并为应用程序中的所有其他实体创建单独的上下文,还是应该将其混合使用.
任何安全问题或理由不在一个上下文中包含我的整个应用程序的所有实体?
所以,我有两个主要对象,会员和公会.一个会员可以拥有一个公会,一个公会可以拥有多个会员.
我在一个单独的DbContext和单独的类库中有Members类.我打算在多个项目中重用这个类库并帮助区分,我将数据库模式设置为"acc".我已经广泛测试了这个库,可以在acc.Members表中添加,删除和更新成员.
公会课程如下:
public class Guild
{
public Guild()
{
Members = new List<Member>();
}
public int ID { get; set; }
public int MemberID { get; set; }
public virtual Member LeaderMemberInfo { get; set; }
public string Name { get; set; }
public virtual List<Member> Members { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
与映射:
internal class GuildMapping : EntityTypeConfiguration<Guild>
{
public GuildMapping()
{
this.ToTable("Guilds", "dbo");
this.HasKey(t => t.ID);
this.Property(t => t.MemberID);
this.HasRequired(t => t.LeaderMemberInfo).WithMany().HasForeignKey(t => t.MemberID);
this.Property(t => t.Name);
this.HasMany(t …Run Code Online (Sandbox Code Playgroud) 这更像是一个"为什么我们做事"的问题,因为我的实际问题已经解决,但我不知道为什么.
我正在处理我的CountyRepository中的以下代码:
public IEnumerable<County> GetCounties(string stateAbbr)
{
using (var db = new AppDbContext())
{
State state = (from s in db.States
where s.Abbr == stateAbbr
select s).First();
return context.Counties.Where(c => c.StateID == state.StateID).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
我在上面创建的AppDbContext将转到自定义初始化程序:
public class AppDbContextInitializer : DropCreateDatabaseIfModelChanges<AppDbContext>
{
protected override void Seed(AppDbContext context)
{
StatesList states = new StatesList();
context.States.AddRange(states);
context.Counties.AddRange(new CountiesList(states));
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我执行代码时,AppDbContext将在Initializer中正确加载State和County信息,但是当它返回到County Repository时,AppDbContext为空并且由于"State没有无参数构造函数"而会出错.我不希望我的State对象有一个无参数构造函数所以我整天都在寻找解决为什么AppDbContext在County Repository中加载错误的方法.我终于找到了以下解决方案:
这是一个简单的解决方案.添加无参数构造函数并将其标记为Obsolete.我这样做了,效果很好.
我的问题是,我为什么要这样做?我使用自定义初始化程序检查了CodeFirst的多个示例,但没有提到需要空构造函数或将其标记为已过时.
是否有更好的解决方案或至少是解释,以便我可以提前知识而不是混乱?
如您所知,最新版本的Visual Studio 2017放弃了'project.json' .csproj而是使用了它.
我正在使用RTM版本,并希望按照本指南从现有数据库生成模型.我在最后一步遇到错误:
Package Manager控制台的Entity Framework Core命令尚不支持基于csproj的.NET Core项目.请改用.NET命令行工具(即dotnet ef).有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=834381.
发生错误后,我使用了它提到的链接切换到dotnet ef.这是我的包管理器命令:
PM> dotnet ef dbcontext scaffold"Server =.; Database = Jumpstart; Trusted_Connection = True;" Microsoft.EntityFrameworkCore.SqlServer
然后错误再次出现:
dotnet:找不到匹配命令"dotnet-ef"的可执行文件
我使用了help命令,发现dotnet没有名为ef的命令.
我只想从现有数据库生成模型.
我在使用DbContext发送SQL语句时遇到问题context.Database.ExecuteSqlCommand().
我正在努力执行
CREATE TABLE Phones([Id] [uniqueidentifier] NOT NULL PRIMARY KEY,
[Number] [int],[PhoneTypeId] [int])
GO
ALTER TABLE [dbo].[Phones] ADD CONSTRAINT [DF_Phones_Id]
DEFAULT (newid()) FOR [Id]
GO
Run Code Online (Sandbox Code Playgroud)
这与错误字符串失败
Incorrect syntax near the keyword 'ALTER'.
Incorrect syntax near 'GO'.
Run Code Online (Sandbox Code Playgroud)
但是,在SSMS中运行该确切语句运行时没有错误?我需要通过DbContext解决有关默认约束的任何问题.我看到人们使用约束而没有将IsDbGenerated设置为true的问题.我不知道这会如何适用于此.
dbcontext ×10
c# ×6
.net ×2
asp.net ×1
asp.net-mvc ×1
automapper ×1
foreign-keys ×1
repository ×1
viewmodel ×1
wpf ×1