c# - Entity Framework ,返回日期错误

标签 c# .net entity-framework

我正在尝试为我的 API 使用 Entity Framework ,但在尝试按日期对对象列表进行排序后,出现了问题。

我的目标是每天废弃一个网页,将产品保存在数据库中,并使用我的 API 访问它。

正如您将在下面看到的,SQL DB 中的数据是正确的,但是使用 Entity Framework ,它将返回同一日期的 2 倍。

我的数据库是:

CREATE TABLE [dbo].[ScrappedProducts] (
    [Domain]          VARCHAR (50)    NOT NULL,
    [ProductId]       VARCHAR (50)    NOT NULL,
    [ScrappedDate]    DATE            NOT NULL,
    [ProductUrl]      VARCHAR (256)   NOT NULL,
    [ProductName]     VARCHAR (200)   NOT NULL,
    [ProductBrand]    VARCHAR (200)   NOT NULL,
    [ProductType]     VARCHAR (100)   NOT NULL,
    [ProductAlcool]   DECIMAL (16, 2) NOT NULL,
    [ProductQuantity] INT             NOT NULL,
    [ProductContain]  DECIMAL (16, 2) NOT NULL,
    [ProductPrice]    DECIMAL (16, 2) NOT NULL,
    [ProductImageUrl] VARCHAR (256)   NOT NULL,
    PRIMARY KEY CLUSTERED ([ProductId] ASC, [Domain] ASC, [ScrappedDate] ASC)
);

我的类(class)是:

namespace WebScrapperAPI.Components
{
    public class Product
    {
        public string Domain { get; set; }
        public DateTime ScrappedDate {get;set;}
        public string ProductId { get; set; }
        public string ProductUrl { get; set; }
        public string ProductName { get; set; }
        public string ProductBrand { get; set; }
        public string ProductType { get; set; }
        public decimal ProductAlcool { get; set; }
        public int ProductQuantity { get; set; }
        public decimal ProductContain { get; set; }
        public decimal ProductPrice { get; set; }
        public string ProductImageUrl { get; set; }

    }
}

我的 DbContext 类是:

using Microsoft.EntityFrameworkCore;
using WebScrapperAPI.Components;

namespace WebScrapperAPI.Data
{
    public class ScrapperDBContext : DbContext
    {
        public DbSet<Product> ScrappedProducts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string connectionString = "Server=tcp:xxx,xxx;Initial Catalog=xxx;Persist Security Info=False;User ID=xxx;Password=xxx;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";


            var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.AddConsole(); // Ajouter la journalisation sur la console
                builder.AddFilter(DbLoggerCategory.Database.Command.Name, LogLevel.Information); // Filtrer les logs SQL uniquement
            });
            optionsBuilder.UseSqlServer(connectionString)
                .UseLoggerFactory(loggerFactory)
                .LogTo(Log, new[] { DbLoggerCategory.Database.Command.Name }, LogLevel.Information);
        }
        private void Log(string t)
        {
            File.WriteAllText("test.txt", t);
        }
    }
}

数据库值:

Auchan  0067c78b-7b53-4e2a-b655-d9c071a5ca87    2023-07-18  https://www.auchan.fr/valauria-muscat-vin-doux-naturel-de-rivesaltes-aop-15-5/pr-C1211479   Muscat vin doux naturel de Rivesaltes AOP   VALAURIA    Liquor  15.50   1   75.00   6.65    /static/images/pixel.png

Auchan  0067c78b-7b53-4e2a-b655-d9c071a5ca87    2023-07-19  https://www.auchan.fr/valauria-muscat-vin-doux-naturel-de-rivesaltes-aop-15-5/pr-C1211479   Muscat vin doux naturel de Rivesaltes AOP   VALAURIA    Liquor  15.50   1   75.00   6.65    /static/images/pixel.png

Entity Framework 值:

{
    "domain": "Auchan",
    "scrappedDate": "2023-07-18T00:00:00",
    "productId": "0067c78b-7b53-4e2a-b655-d9c071a5ca87",
    "productUrl": "https://www.auchan.fr/valauria-muscat-vin-doux-naturel-de-rivesaltes-aop-15-5/pr-C1211479",
    "productName": "Muscat vin doux naturel de Rivesaltes AOP",
    "productBrand": "VALAURIA",
    "productType": "Liquor",
    "productAlcool": 15.5,
    "productQuantity": 1,
    "productContain": 75,
    "productPrice": 6.65,
    "productImageUrl": "/static/images/pixel.png"
  },
  {
    "domain": "Auchan",
    "scrappedDate": "2023-07-18T00:00:00",
    "productId": "0067c78b-7b53-4e2a-b655-d9c071a5ca87",
    "productUrl": "https://www.auchan.fr/valauria-muscat-vin-doux-naturel-de-rivesaltes-aop-15-5/pr-C1211479",
    "productName": "Muscat vin doux naturel de Rivesaltes AOP",
    "productBrand": "VALAURIA",
    "productType": "Liquor",
    "productAlcool": 15.5,
    "productQuantity": 1,
    "productContain": 75,
    "productPrice": 6.65,
    "productImageUrl": "/static/images/pixel.png"
  }

编辑:我的查询

public static IEnumerable<Product> GetProducts()
{
    var products = new List<Product>();
    using (var context = new ScrapperDBContext())
    {
        products = context.ScrappedProducts.ToList();
    }
    return products;
}

最佳答案

导致该问题的原因是应用程序实体Product 的主键与表不同。由于类或 DbContex 的 OnModelBuilding 中均未指定键,因此按惯例使用属性 ProductID

不过,该表使用PRIMARY KEY CLUSTERED ([ProductId] ASC, [Domain] ASC, [ScrappedDate] ASC),这意味着同一ProductId<总是有多个行。当 EF 多次看到相同的 PK 值时,它会返回相同的缓存对象。

要解决此问题,必须显式指定复合主键:

    protected override void OnModelCreating(DbModelBuilder builder)
    {
        builder.Entity<Product>().HasKey(p=> new {
            p.ProductId, 
            p.Domain,
            p.ScrappedDate});
    }

这不是一个错误。主键是内存中实体的身份,因此相同的 PK 值必须返回相同的对象。否则,应用程序可能会发现自己正在读取一个对象并修改另一个对象,即使它们应该是同一个对象。

ORM(例如 NHibernate、Entity Framework 以及基本上所有跟踪对象而不仅仅是映射结果的东西)都使用 PK 值作为对象的标识。他们的工作是给人一种使用内存中实体的印象,而不是表和行。通过身份请求相同的对象,应该始终返回相同的内存对象。

关于c# - Entity Framework ,返回日期错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76722503/

相关文章:

c# - 如何以编程方式获取 Windows Azure 中的虚拟机列表

.NET 正则表达式匹配不正确

c# - 项目已过时 - 不再显示此对话框 - 构建还是不构建?

asp.net-mvc - 在 Entity Framework 中使用语句

为 32 位系统编译的 C# 程序和 C++ DLL 在 64 位系统上崩溃

c# - 如何等待来自不同线程的异步 UI 方法?

c# - 如何统计我的列的总数?

c# - 字符串操作。在 2 个索引之间查找字符串

c# - 如何使用 Entity Framework 在数据库中存储链表(具有下一个和上一个键的实体)?

c# - 使用 linq to Entity 框架按日期读取最近插入的行