EF6。
我首先使用EF6数据库。
我的数据库表在6列上有唯一键。一切都在项目中运作良好。然后我意识到唯一键是不正确的,我不需要它,所以我从数据库中删除它。
我有Product
,其中包含ICollection<ProdPrice> ProdPrices
。
现在,当我使用Product product = db.Products.Find(id);
时,我得到了一个产品,但ProdPrices集合只包含6个应该包含12个项目。(前6个项目在列表中)。
如果我从数据库中删除第一项并再次运行代码,则会返回6项 - 项目2 - 7.
如果我更改了列中 列中的某个值,那么该项中的项将会出现在
中。所以我认为EF在某种程度上记住了唯一键,只返回了与唯一键不冲突的第一项。
我试图在edml文件中“从数据库更新模型” - 没有解决问题。所以我从edml中删除了ProdPrice表,“从数据库更新模型” - 没有用。
所以我的问题是 - 我是否正确说EF正在记住已删除的唯一密钥?如果是,我如何让它忘记呢?如果我不对,那你可以解释实际发生的事情吗?
编辑:通过调用数据库生成的SQL - 标准select语句,它在SSMS中运行时返回所有12条记录(为便于阅读而删除列):
SELECT
[Extent1].[ProdPriceID] AS [ProdPriceID],
[Extent1].[ProdID] AS [ProdID],
[Extent1].[PermanentlyDelete] AS [PermanentlyDelete],
[Extent1].[DateCreated] AS [DateCreated]
FROM [dbo].[ProdPrice] AS [Extent1]
WHERE [Extent1].[ProdID] = 67577
以下是结果,因此您可以看到我获得了12条记录。
代码结果:
所以我决定只要求产品的价格 - 我得到12个结果,这真让我感到困惑:
编辑: 我以为我已经解决了...... 为了解决(并进一步测试),我决定在db中重新创建ProdPrice表 - 我这样做是通过使用MSSSMS生成脚本并包含数据,因此我有一个表的精确副本,称之为ProdPrice2。
我的系统中有ProdPrice和ProdPrice2实体(这确认我仍然连接到正确的数据库)。 ProdPrice仍然只返回与原始唯一索引不冲突的记录。 ProdPrice2 - 返回所有记录!
哎呀,以为就是这样 - 然后我从我的系统中删除了ProdPrice,离开了ProdPrice2 - 我运行了系统,ProdPrice2现在只有6条记录,而不是之前的12条记录!
我添加了ProdPrice.ProdPrice2仍然有6条记录,ProdPrice现在已经有了所有预期记录。
我被殴打!!!!这真的阻止了我的发展!在解决之前我不能继续!
答案 0 :(得分:3)
经过几天的摔跤和@AlbertoMonteiro的一些出色的帮助和建议,我无法得到我期望的行为。
在继续尝试各种各样的事情和调试之后,我最终点击了一些我忘记在那里的代码......!
原来问题的答案
Entity Framework Database是否首先了解数据库中设置的唯一键?
是,没有实体框架数据库首先了解数据库中设置的唯一密钥。
但是,EF会在创建实体列表时使用任何重写的Equals()函数。在我的代码中,我已经覆盖了Equals函数来模仿数据库中的唯一键,这意味着当我添加到我可以匹配的价格列表时,重复&#34;重复&#34;并将它们合并在一起。这段代码导致我的价格列表没有完全填充,因为我改变了我希望系统工作的方式。
答案是我是个白痴,我应该记住我写过的代码。我会在这里留下这个问题,因为这可能会阻止某人在将来失去几天的发展。
答案 1 :(得分:1)
此问题中的实体框架,不用担心您删除的唯一密钥,此唯一密钥也不会在您选择内容时过滤数据,唯一密钥可防止您无法添加具有相同唯一密钥的另一行
同样,这个独特的密钥并不是一个麻烦,EF并不关心它。
但是你可以调试从EF生成的SQL并检查为什么你只从属性 ProdPrices 获得6个项目。
我们可以使用上下文中的 Database.Log 属性来分析生成的SQL。
你说你有这个代码行Product product = db.Products.Find(id);
让我们稍微修改它来分析sql。
//Add breakpoint in this line
Product product = db.Products.Find(id);
db.Database.Log = sql => System.Diagnostics.Debug.WriteLine(sql);
var prodPrices = product.ProdPrices.ToList();
//Next line
分析SQL查询,在SSMS中执行并检查结果。
我在我的机器上尝试了这个,但它运行正常:
public class Program
{
public static void Main(string[] args)
{
using (var ctx = new MyClass())
{
if (!ctx.Products.Any())
{
var product = new Product
{
ProdPrices = new List<ProdPrice>
{
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,29,18,28,27)},
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,29,18,28,28)},
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,29,18,28,28)},
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,29,18,28,29)},
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,29,18,28,29)},
new ProdPrice {PermanentlyDelete = true, DateCreated = new DateTime(2015,12,30,19,08,38)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,06)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,06)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,07)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,07)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,08)},
new ProdPrice {PermanentlyDelete = false, DateCreated = new DateTime(2015,12,31,10,18,08)},
}
};
ctx.Products.Add(product);
ctx.SaveChanges();
Console.WriteLine("Saved");
}
}
using (var ctx = new MyClass())
{
var product = ctx.Products.Find(1);
var count = product.ProdPrices.Count;
Console.WriteLine(count);
}
}
}
public class MyClass : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<ProdPrice> ProdPrices { get; set; }
}
public class Product
{
[Key]
public long ProdID { get; set; }
public virtual ICollection<ProdPrice> ProdPrices { get; set; }
}
public class ProdPrice
{
public long ProdPriceID { get; set; }
public bool PermanentlyDelete { get; set; }
public DateTime DateCreated { get; set; }
}
答案 2 :(得分:0)
您似乎只创建了一次dbcontext,这也是静态的。
当您对db进行fetch / write调用时,创建一个新的上下文,应该这样做。
再次,
创建一个包含DbContext的基类,并在每次需要与db通信时继承该类。
像这样的东西
public class TheDBEntities
{
private TheDBEntities _context = new TheDBEntities();
protected TheDBEntities Context { get; private set; }
protected TheDataContext()
{
Context = _context;
}
protected void SaveChanges()
{
Context.SaveChanges();
}
protected void SaveChangesAsync()
{
Context.SaveChangesAsync();
}
}
public class DBBusinessLayer: TheDBEntities
{
public DBBusinessLayer() { }
public void GetData(int id)
{
// use it here Context.<yourentities>
}
}