gpt4 book ai didi

c# - 我可以使用Entity Framework版本6或7自动更新对象及其子对象吗?

转载 作者:IT王子 更新时间:2023-10-29 04:30:49 28 4
gpt4 key购买 nike

我有三张桌子。 Word-> WordForm-> SampleSentence。每个Word具有不同的WordForms,然后每种形式可以具有一个或多个SampleSentence

CREATE TABLE [dbo].[Word] (
[WordId] VARCHAR (20) NOT NULL,
[CategoryId] INT DEFAULT ((1)) NOT NULL,
[GroupId] INT DEFAULT ((1)) NOT NULL,
PRIMARY KEY CLUSTERED ([WordId] ASC),
CONSTRAINT [FK_WordWordCategory] FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[WordCategory] ([WordCategoryId]),
CONSTRAINT [FK_WordWordGroup] FOREIGN KEY ([GroupId]) REFERENCES [dbo].[WordGroup] ([WordGroupId])
);

CREATE TABLE [dbo].[WordForm] (
[WordFormId] VARCHAR (20) NOT NULL,
[WordId] VARCHAR (20) NOT NULL,
[Primary] BIT DEFAULT ((0)) NOT NULL,
[PosId] INT NOT NULL,
[Definition] VARCHAR (MAX) NULL,
PRIMARY KEY CLUSTERED ([WordFormId] ASC),
CONSTRAINT [FK_WordFormPos] FOREIGN KEY ([PosId]) REFERENCES [dbo].[Pos] ([PosId]),
CONSTRAINT [FK_WordFormWord] FOREIGN KEY ([WordId]) REFERENCES [dbo].[Word] ([WordId])
);


CREATE TABLE [dbo].[SampleSentence] (
[SampleSentenceId] INT IDENTITY (1, 1) NOT NULL,
[WordFormId] VARCHAR (20) NOT NULL,
[Text] VARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_SampleSentence] PRIMARY KEY CLUSTERED ([SampleSentenceId] ASC),
CONSTRAINT [FK_SampleSentenceWordForm] FOREIGN KEY ([WordFormId]) REFERENCES [dbo].[WordForm] ([WordFormId])
);

我将从这些表中获取数据到前端客户端,然后修改数据并添加或删除WordForms和SampleSentences。

然后,我将数据带回服务器。

Entity Framework是否可以通过某种方式检查以查看带回服务器并更改数据库的对象中的更改,还是必须做某种形式的比较,以检查Word,WordForm的前后和样本句对象?

供引用的是我正在使用的C#对象:
public class Word
{
public string WordId { get; set; } // WordId (Primary key) (length: 20)
public int CategoryId { get; set; } // CategoryId
public int GroupId { get; set; } // GroupId

// Reverse navigation
public virtual System.Collections.Generic.ICollection<WordForm> WordForms { get; set; } // WordForm.FK_WordFormWord

// Foreign keys
public virtual WordCategory WordCategory { get; set; } // FK_WordWordCategory
public virtual WordGroup WordGroup { get; set; } // FK_WordWordGroup

public Word()
{
CategoryId = 1;
GroupId = 1;
WordForms = new System.Collections.Generic.List<WordForm>();
}
}

public class WordForm
{
public string WordFormId { get; set; } // WordFormId (Primary key) (length: 20)
public string WordId { get; set; } // WordId (length: 20)
public bool Primary { get; set; } // Primary
public int PosId { get; set; } // PosId
public string Definition { get; set; } // Definition

// Reverse navigation
public virtual System.Collections.Generic.ICollection<SampleSentence> SampleSentences { get; set; } // SampleSentence.FK_SampleSentenceWordForm

// Foreign keys
public virtual Pos Pos { get; set; } // FK_WordFormPos
public virtual Word Word { get; set; } // FK_WordFormWord

public WordForm()
{
Primary = false;
SampleSentences = new System.Collections.Generic.List<SampleSentence>();
}
}

public class SampleSentence : AuditableTable
{
public int SampleSentenceId { get; set; } // SampleSentenceId (Primary key)
public string WordFormId { get; set; } // WordFormId (length: 20)
public string Text { get; set; } // Text

// Foreign keys
public virtual WordForm WordForm { get; set; } // FK_SampleSentenceWordForm
}

到目前为止,这是我能想到的,但这不包括检查SampleSentence,而且我不确定该怎么做:
    public async Task<IHttpActionResult> Put([FromBody]Word word)
{
var oldObj = db.WordForms
.Where(w => w.WordId == word.WordId)
.AsNoTracking()
.ToList();
var newObj = word.WordForms.ToList();

var upd = newObj.Where(n => oldObj.Any(o =>
(o.WordFormId == n.WordFormId) && (o.PosId != n.PosId || !o.Definition.Equals(n.Definition) )))
.ToList();
var add = newObj.Where(n => oldObj.All(o => o.WordFormId != n.WordFormId))
.ToList();
var del = oldObj.Where(o => newObj.All(n => n.WordFormId != o.WordFormId))
.ToList();
foreach (var wordForm in upd)
{
db.WordForms.Attach(wordForm);
db.Entry(wordForm).State = EntityState.Modified;
}
foreach (var wordForm in add)
{
db.WordForms.Add(wordForm);
}
foreach (var wordForm in del)
{
db.WordForms.Attach(wordForm);
db.WordForms.Remove(wordForm);
}
db.Words.Attach(word);
db.Entry(word).State = EntityState.Modified;
await db.SaveChangesAsync(User, DateTime.UtcNow);
return Ok(word);
}

最佳答案

抱歉,没有
从字面上看,您的问题的答案(如标题中所示)是 no 。使用 Entity Framework 无法自动执行此操作。在所谓的断开连接的场景中,开发人员应该照顾好自己,正确保存来自客户端的更改。
如前所述,EF曾经拥有自我跟踪实体,但是很快这种方法称为deprecated,尽管在官方文档中从未明确说明原因。可能是因为“STEs made (change tracking) easier, but at the cost of making almost everything else really hard.”。它与带有t4模板的数据库优先生成的类模型完美地适合ObjectContext API,但是,众所周知,DbContext API和code-first已成为EF推荐的(并且很快成为唯一受支持的)体系结构。当然,通过代码优先,EF不能强制执行任何STE实现。
或者...?
令人沮丧的是,EF以后再也没有填补这个空白,例如,通过提供类似于GraphDiff提供的API(或者也许现在我应该说提供)的API。我知道有两种合理的选择。
Entity Framework 的命题
Lerman和Miller在他们的《编程 Entity Framework 》一书中:
DbContext提出了一种替代技术,该技术与EF团队到目前为止提出的自我跟踪实体的替代方法最接近。它围绕以下接口(interface)展开:

public interface IObjectWithState
{
State State { get; set; }
Dictionary<string, object> OriginalValues { get; set; }
}
State在哪里
public enum State
{
Added,
Unchanged,
Modified,
Deleted
}
为了使此方法正常工作,每个实体都应实现该接口(interface)。此外,每个 DbContext子类都需要许多方法。实现实体时填充 OriginalValues属性的方法,以及当将其返回上下文时将其更改跟踪器与实体中记录的更改同步的方法。在此处复制所有这些代码实在太多了,您可以在本书的第102页开始找到它。
好吧,如果实现所有这些功能,那么您将拥有各种自跟踪实体。它相当复杂,尽管一旦实现,它将“正常工作”。但是,一个主要缺点是,添加或删除实体时,上下文的所有使用者都必须设置此 State属性。强加给客户端代码是一项艰巨的责任!
微风
Breeze提供了一个完整的解决方案,从您的服务中的DAL一直到客户端中的javascript代码。这既方便又令人恐惧。
在javascript中,您会得到类似LINQ的语法:
var query = breeze.EntityQuery
.from("Customers")
.where("CompanyName", "startsWith", "A")
.orderBy("CompanyName");
这与C#代码中的Breeze的 EntityManager通信:
var manager = new Breeze.Sharp.EntityManager(serviceName);
var results = await manager.ExecuteQuery(query);
这个 EntityManager基本上是EF上下文的包装器。如果所有 Activity 部件均已正确设置,则它几乎可以将EF上下文带到您的JavaScript中,并具有更改跟踪,保存更改等内容。我在一个项目中使用它,实际上,它非常方便。
但是,如果您使用Breeze,那就一直都是Breeze。它影响到一切。数据库架构的更改需要javascript的更改。这很可怕,但是您可以习惯。但是,如果您想以自己的方式做事,那么使Breeze满足您的需求变得非常困难(尽管并非不可能)。就像和婆婆一起生活。我认为,在很多情况下,微风和其他模式的结合最终是不可避免的。
但是你还是要吗?
一般而言,对断开连接的实体进行任何自动跟踪的主要缺点是,使用原始实体对象进行数据传输非常容易。问题是,在大多数情况下,完整实体包含的数据远远多于客户端所需(或允许查看)的数据。使用专用的薄型DTO可以显着提高性能。当然,它们充当DAL与UI/ Controller 之间的抽象层。
是的,使用DTO,我们总是必须在服务器端“重绘状态”。随它吧。对于断开连接的场景,确实是推荐的方法。
John Papa在有关SPA的热毛巾模板的PluralSight类(class)中,在解释Breeze时认识到了这个问题。他提出了“部分实体”的解决方案。这是一个解决方案,但相当复杂且笨拙。当然,实体仍然是数据传输的基础。

关于c# - 我可以使用Entity Framework版本6或7自动更新对象及其子对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36878706/

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