gpt4 book ai didi

c# - 为什么我不能通过 Entity Framework 覆盖某个字段?

转载 作者:行者123 更新时间:2023-11-30 17:29:53 25 4
gpt4 key购买 nike

我正在开发一个使用 Entity Framework 的 ASP.NET MVC 应用程序。我要改字段CreatedOnUsers表。

下面的代码

    using (var db = new MainDB())
{
var theUser = db.Users.Single(u => u.LoginName == model.User.LoginName);
theUser.CreatedOn = new DateTime(2017, 1, 1); // this does not save
theUser.CF20 = "test20";
db.SaveChanges();
}

更改字段 CF20到“test20”,但它不会改变 CreatedOn字段。

我假设 CreatedOn字段在某个地方被赋予了一些特殊的状态和功能,在创建记录时用时间戳填充它,并防止它在之后被更改。

我找不到它在代码中的什么位置,所以我假设它在 Entity Framework 模型、设置等中的某个地方。

我在哪里可以找到它的设置位置以及设置后如何更改它?

附录

例如,我在 <EntityType Name="Users"> 下的一个 .edmx 文件中找到这条线 <Property Name="CreatedOn" Type="datetime" Nullable="false" StoreGeneratedPattern="Computed" />并将其更改为 <Property Name="CreatedOn" Type="datetime" Nullable="false" />但它仍然将日期计算为日期时间并且不会更改它。

并输出原始 SQL,我在 update 中看到声明,它离开 CreatedOn out:我的 SQL 输出显示:

UPDATE [dbo].[Users]
SET [LoginName] = @0,
[Password] = @1,
[PasswordSalt] = @2,
[LastLoginIP] = NULL,
[Status] = @3,
[Email] = @4,
[FailedLoginAttempts] = NULL,
[CF01] = NULL,
[CF02] = NULL,
[CF03] = NULL,
[CF04] = NULL,
[CF05] = NULL,
[CF06] = NULL,
[CF07] = NULL,
[CF08] = NULL,
[CF09] = NULL,
[CF10] = NULL,
[LanguageID] = @5,
[CF11] = NULL,
[CF12] = NULL,
[CF13] = NULL,
[CF14] = NULL,
[CF15] = NULL,
[CF16] = NULL,
[CF17] = NULL,
[CF18] = NULL,
[CF19] = @6,
[CF20] = @7,
[MustChangePassword] = NULL
WHERE ([ID] = @8)

最佳答案

这可能是 SQL Server 中的一个计算列,因此在您的代码中没有任何地方实际设置它 - 它是在最初添加行时在服务器上完成的。 EF 不会在更新查询中包含计算列,并将在更新查询后读回列以从数据存储中加载可能更新的值。

讨论后更新:

这是一个最小的解决方案,其中默认值按需正确更新。

首先在 SQL Server 上创建一个新表:

CREATE TABLE [dbo].[DateDefaultTest](
[AnId] [int] IDENTITY(1,1) NOT NULL,
[CreatedOn] [datetime2](7) NOT NULL,
[SomeField] [nvarchar](50) NULL,
CONSTRAINT [PK_DateDefaultTest] PRIMARY KEY CLUSTERED
(
[AnId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[DateDefaultTest] ADD CONSTRAINT [DF_DateDefaultTest_CreatedOn] DEFAULT (getutcdate()) FOR [CreatedOn]
GO

它有一个 ID 字段作为自动递增的主键,一个字符串字段和我们感兴趣的 CreatedOn 字段。我们添加了一个 DEFAULT 约束以将其设置为当前 UTC 日期和时间。

接下来,创建一个控制台应用程序,通过 NuGet 添加 EF 并像往常一样设置 DbContext。我将我的上下文称为 DefaultTestEntities

实体的生成代码如下:

public partial class DateDefaultTest
{
public int AnId { get; set; }
public System.DateTime CreatedOn { get; set; }
public string SomeField { get; set; }
}

在 EF 图的 CreatedOn 字段的属性页中,没有任何更改。

使用以下代码添加几行:

using (var db = new DefaultTestEntities())
{
db.DateDefaultTests.Add(new DateDefaultTest
{
SomeField = "Bananas"
});
db.DateDefaultTests.Add(new DateDefaultTest
{
SomeField = "Apples",
});

db.SaveChanges();
}

这些应该出现在表格中,并按预期设置当前日期和时间。

正如您所发现的,如果您尝试在插入新行时手动设置 CreatedOn,由于 SQL Server 的约束,这将不起作用。例如:

db.DateDefaultTests.Add(new DateDefaultTest
{
SomeField = "Pears",
CreatedOn = DateTime.UtcNow.AddHours(1)
});

将导致设置无意义的“0001-01-01”日期。

如果您想显式设置 CreatedOn,则必须更新现有行。为此:

db.DateDefaultTests
.Where(x => x.SomeField == "Bananas")
.First()
.CreatedOn = DateTime.UtcNow.AddDays(-1);
db.SaveChanges();

如果这不适用于您的情况,我建议您:

  • 检查 SQL Server 中的列以确保未计算该值
  • 重新生成模型
  • 确认您的代码中没有 EF 覆盖,这可能会影响保存实体时的值

对于我说 EF 不会更新默认列的评论,我深表歉意。这是不正确的,仅适用于初始插入。

更新 - 所需设置:

SQL Server CreatedOn Settings

EDMX CreatedOn Settings

关于c# - 为什么我不能通过 Entity Framework 覆盖某个字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50619127/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com